确定path是否是Node.js中另一个path的子目录

我正在为我想为其中有一个事件侦听器的每个父目录发出事件的MQTT处理程序 。 例如:

如果有以下MQTTpath可用,那里有下标 – 有这些path的事件监听器 –

  • test
  • replyer/request
  • test/replyer/request

而有人在主题test/replyer/request/@issuer ,应该有2个事件: testtest/replyer/request

鉴于任何path都是可能的,并没有可用的有效事件列表,我们必须检查path是否是另一个父path。 我们可以用正则expression式吗? 如果是这样,它会是什么样子? 有更简单/更有效的解决scheme吗?

使用indexOf就足够了。

 function isParentOf(parent, dir) { return dir.indexOf(parent) === 0; } isParentOf('test/replyer/request/@issuer', 'test') // true isParentOf('test/replyer/request/@issuer', 'replyer/request') // false isParentOf('test/replyer/request/@issuer', 'test/replyer/request') // true 

请忽略接受的答案。 它不能以任何身份工作。 从来没有,永远不会。

2017年末答案

在ES6中。

 const isChildOf = (child, parent) => { if (child === parent) return false const parentTokens = parent.split('/').filter(i => i.length) return parentTokens.every((t, i) => child.split('/')[i] === t) } 

如果您正在使用node.js,并且想要跨平台,请包含path模块,并用split(path.sep)replacesplit('/') split(path.sep)


怎么运行的:

所以,你想知道一个目录(比如home/etc/subdirectory )是否是另一个目录的子目录(比如home/etc )。

它采用假设的childpath和parentpath,并使用split将它们转换为数组:

 ['home', 'etc', 'subdirectory'], ['home', 'etc'] 

然后遍历parent数组中的所有令牌,并使用ES6的.every()对它们在child数组中的相对位置逐一进行检查。

如果父母的一切都与孩子的一切相符,知道我们已经排除他们完全相同的目录(使用child !== parent ),我们将得到我们的答案。

让节点本身做的工作。

 const path = require('path'); const relative = path.relative(parent, dir); return !!relative && !relative.startsWith('..') && !path.isAbsolute(relative); 

它也为你做标准化。

 const path = require('path'); const tests = [ ['/foo', '/foo'], ['/foo', '/bar'], ['/foo', '/foobar'], ['/foo', '/foo/bar'], ['/foo', '/foo/../bar'], ['/foo', '/foo/./bar'], ['/bar/../foo', '/foo/bar'], ['/foo', './bar'], ['C:\\Foo', 'C:\\Foo\\Bar'], ['C:\\Foo', 'C:\\Bar'], ['C:\\Foo', 'D:\\Foo\\Bar'], ]; tests.forEach(([parent, dir]) => { const relative = path.relative(parent, dir); const isSubdir = !!relative && !relative.startsWith('..') && !path.isAbsolute(relative); console.log(`[${parent}, ${dir}] => ${isSubdir} (${relative})`); }); 

也可以跨驱动器在Windows上运行。

 [/foo, /foo] => false () [/foo, /bar] => false (..\bar) [/foo, /foobar] => false (..\foobar) [/foo, /foo/bar] => true (bar) [/foo, /foo/../bar] => false (..\bar) [/foo, /foo/./bar] => true (bar) [/bar/../foo, /foo/bar] => true (bar) [/foo, ./bar] => false (..\Users\kozhevnikov\Desktop\bar) [C:\Foo, C:\Foo\Bar] => true (Bar) [C:\Foo, C:\Bar] => false (..\Bar) [C:\Foo, D:\Foo\Bar] => false (D:\Foo\Bar) 

用正则expression式来做是一种方法(对于每个有事件监听器的path,检查发布的主题是否以该path开始),但是因为更有可能你会有很多不同的path,比你长得荒谬url,打破发表的话题可能会更有效率。

像这样的东西可能更容易阅读:

编辑 : @huaoguo是绝对正确的,indexOf === 0是我们真正需要的!

 let paths = [ 'test', 'replyer/request', 'test/replyer/request' ] let topic = 'test/replyer/request/@issuer' let respondingPaths = (paths, topic) => paths.filter(path => topic.indexOf(path) === 0) console.log(respondingPaths(paths, topic)) // ['test', 'test/replyer/request']