Node glob语法
本文 由 Ivan Yan 翻译,“署名-非商用-相同方式共享”,意见反馈。
通过星号等 shell 所用的模式匹配文件。
这是一个 JavaScript 版本的 glob 实现。使用 minimatch 执行匹配操作。
译注:早期 Unix (第 1-6 版,1969-1975)的命令行解释器依赖独立程序 /etc/glob 展开参数中的通配符。这个程序会展开通配符并把展开后的文件列表传给命令。它的名字是 “global command” 的简称。后来这个功能由工具函数 glob() 提供,被 shell 等程序使用。(译自 WikiPedia#Origin)。)
用法
用 npm 安装:
1 | npm i glob |
1 | var glob = require("glob") |
Glob 基础
“Globs” 是像这样的模式:用在命令行中的 ls *.js, 用在 .gitignore 文件中的 build/*。
在解析路径中的模式前,先展开大括号部分。大括号部分以 { 开始,以 } 结束,里面是一个逗号分隔列表。大括号部分可以包含斜杠,例如 a{/b/c,bcd} 将展开为 a/b/c 与 abcd。
译注:比如路径 “/foo/bar”, 其中 “foo” 与 “bar” 是路径片段(path portion)。
下面这些字符在路径片段中有特别的意义:
*匹配路径片段中零个或多个字符。?匹配一个字符。[...]匹配一个字符集合,类似于正则表达式的字符集合。如果第一个字符是!或^那么它匹配一个不在这个字符集合内的字符。!(pattern|pattern|pattern)匹配不匹配模式的文件。?(pattern|pattern|pattern)匹配这些模式零次或一次。+(pattern|pattern|pattern)匹配这些模式一次或多次。*(a|b|c)匹配这些模式零次或多次。@(pattern|pat*|pat?erN)匹配这些模式一次。**即 globstar 模式,如果这是单独的一个路径片断,则匹配零级或多级目录,但不会搜索符号链接目录。
点号
如果文件或目录路径片段的第一个字符是点号(.),那么它将不匹配任何 glob,除非 glob 相应的路径片段的第一个字符也是 .。
例如,a/.*/c 匹配 a/.b/c,但是 a/*/c 不匹配,因为 * 第一个字符不是 .。
可以设置选项 dot:true,将 . 当作普通的字符。
译注:点文件(dot file),名字以 . 开始,在 Unix 下是隐藏文件。即使使用 globstar 模式,a/**/c 也不会匹配 a/.b/c。
匹配基本名
如果设置选项 matchBase:true,并且模式不包含斜杠,那么将搜索目录树下任意地方的匹配基本名(basename)的文件。例如 *.js 匹配 test/simple/basic.js。
空集
如果没有找到匹配的文件,那么返回一个空的数组。这跟 shell 不同,shell 会返回模式。例如:
1 | $ echo a*s*d*f |
想与 shell 一致,设置选项 nonull:true。
其它参考
man shman bash(搜索 “Pattern Matching”)man 3 fnmatchman 5 gitignore- minimatch 文档
glob.hasMagic(pattern, [options])
如果模式包含特殊的字符则返回 true,否则返回 false。
注意选项会影响结果。如果设置了选项 noext:true,则 +(a|b) 不会视为魔法模式。如果模式包含大括号展开式,比如 a/{b/c,x/y},则认为是魔法的,除非设置了选项 nobrace:true。
glob(pattern, [options], cb)
pattern{String}待匹配的模式options{Object}cb {Function}err{Error | null}matches{Array<String>}匹配模式的文件名
进行一个异步的 glob 搜索。
glob.sync(pattern, [options])
pattern{String}待匹配的模式options{Object}- return:
{Array<String>}匹配模式的文件名
进行一个同步的 glob 搜索。
Class: glob.Glob
实例化 glob.Glob 类,创建一个 Glob 对象。
1 | var Glob = require("glob").Glob |
这是一个 EventEmitter 对象,立刻开始遍历文件系统搜索匹配。
new glob.Glob(pattern, [options], [cb])
pattern{String}待匹配的模式options{Object}cb {Function}当遇到错误或找到匹配时调用
err{Error | null}matches{Array<String>}匹配模式的文件名
注意,如果设置了选项 sync,则匹配将立即添加到 g.found。
属性
minimatchglob 所用的 minimatch 对象。options传入的选项。aborted布尔值,当调用abort()时设为 true。取消之后不能继续 glob 搜索,不过可以通过重用 statCache 避免重复调用 syscall。cache缓存。每个字段都可以取下面的值:false- 路径不存在true- 路径存在'FILE'- 路径存在,并且不是目录'DIR'- 路径存在,并且是目录[file, entries, ...]- 路径存在, 并且是目录,数组值是fs.readdir的结果
statCache缓存fs.stat的结果,阻止多次读取同一路径的信息。symlinks记录哪些路径是符号链接,与**解析相关。realpathCache可选对象,传给fs.realpath,以减少不必要的 syscall。它保存在 Glob 实例上,可以重用。
事件
end当结束搜索匹配时触发此事件,包含所有的匹配。如果设置了选项nonull,并且没有找到匹配,则matches包含原来的模式。匹配经过排序,除非设置了选项nosort。match每当找到一个匹配时以这个匹配触发此事件,匹配没有去重,也没有解析为真实路径。error当遇到一个异常时, 或者在设置了options.strict的情况下遇到 fs 错误时触发此事件。abort当调用abort()时触发此事件。
方法
pause暂停搜索。resume继续搜索。abort取消搜索。
选项
所有可以传给 Minimatch 的选项也可以传给 Glob,选项会改变匹配行为。有些选项是新加的,有些选项是 glob 特定选项。
所有选项默认是 false, 除非特别说明。
所有选项也会添加给 Glob 对象。
如果运行多个 glob 操作,可以将一个 Glob 对象作为 options 参数传递给后面的操作,以简化一些 stat 和 readdir 的调用。在最新的版本里,你可以传入共享的 symlinks, statCache, realpathCache, cache 选项,这样并行的 glob 操作将因为共享文件系统的信息而提速。
cwdString,搜索的工作目录,默认为process.cwd()。rootString,以/开始的模式的挂载目录,默认为path.resolve(options.cwd, "/")(Unix 系统下为/,Windows 系统下为C:\或其它磁盘根目录。)dot在常规匹配与globstar匹配中包含点文件。注意,.在模式片断中始终匹配点文件。nomount以/开始的模式默认挂载到 root 选项设置的目录上,因而返回一个合法的文件系统路径。设置此选项禁止此行为。mark给匹配的目录添加一个/字符。注意这会调用stat。nosort不排序结果。statstat 所有的结果。这多少会降低性能,完全没必要,除非认为readdir不能作为文件存在的可靠指示。silent当读取目录时遇到一个不常见的错误,将打印一条警告到 stderr。设置此选项可取消打印。strict当读取目录时遇到一个不常见的错误,进程将继续搜索其它匹配。设置此选项可抛出错误。cacheObject, 见上文。传入之前生成的缓存对象可以节省一些 fs 调用。statCacheObject, 匹配结果的文件系统信息的缓存,用来阻止不必要的stat调用。通常不需要设置此选项。不过如果知道文件系统在不同的 glob() 调用之间不会变化,可以将一个 glob() 调用的 statCache 传给另一个调用的选项(见下面“竞态条件”)。symlinksObject, 已知的符号链接的缓存。可以传入一个之前生成的symlinks对象,在匹配**时节省lstat调用。sync废弃,可以用glob.sync(pattern, opts)。nounique在有些情况下,大括号展开式会导致在结果里面同一文件出现多次。本实现默认阻止结果里面出现重复。此选项禁止此行为。nonull不返回空集,返回一个包含模式的集合,这是 glob(3) 的默认行为。debug启用 minimatch 和 glob 调试。nobrace不展开{a,b}和{1..3}这样的集合。noglobstar不支持 “globstar” 模式,这时**不匹配多级文件名,像普通的*一样对待。noext不支持 “extglob” 模式,比如+(a|b)。nocase匹配不区分大小写。注意:在不区分大小写的系统里,默认匹配没有特殊字符的模式,因为stat和readdir不会抛出异常。matchBase如果模式不包含斜杠则匹配基名字。例如*.js将视为**/*.js,匹配所有目录下的 js 文件。nodir不匹配目录,只匹配文件。注意如果只匹配目录,简单地在模式的末尾放一个/即可。ignore添加一个模式或一个 glob 模式数组,用来排除匹配。注意:ignore模式始终认为dot:true,不管其它的配置是怎样的。follow在展开**时追踪符号链接目录。注意这可能导致大量重复的引用(循环链接)。realpath在所有的结果上调用fs.realpath,在不能解析符号链接的情况下,返回匹配文件的全路径,不过它常常是一个损坏的符号链接。absolute设为 true 时始终得到匹配文件的绝对地址。不同于realpath,这同时影响match事件的返回值。
与其它 fnmatch/glob 实现的比较
严格地兼容现实规范是值得追求的目标,不过 node-glob 与其它实现之间存在差异,并且是有意的。
默认支持 **,除非设置了选项 noglobstar。这也是 bsdglob 和 bash 4.3 的方式。只有当 ** 是单独的一个路径片段时它才有这种特殊意义。例如 a/**/b 匹配 a/x/y/b,但是 a/**b 不会。
注意,** 不会搜索符号链接目录,尽管它们可能匹配模式的其它片断。这可以防止无限循环、重复等。
如果转义的模式没有找到匹配,并且设置了选项 nonull,则 glob 原样返回模式,而不是转义后的模式。例如 glob.match([], "\\*a\\?") 返回 "\\*a\\?" 而不是 "*a?"。默认的行为类似于在 bash 里设置 nullglob 选项,除了 bash 不会解析转义的模式。
如果没有禁止展开大括号,则在解析 glob 的其它模式之前先展开它。例如 +(a|{b),c)},在 bash 或 zsh 下面是无效的,在这儿会先展开为 +(a|b) 和 +(a|c),再检查这两个模式的有效性。既然它们是有效的,则进行匹配。
注释与排除
在之前的版本中,如果模式以 # 开始则它是一个注释。标记为注释。如果模式以 ! 开始则它是一个排除模式。
v5 已经废弃了选项 nonegate 和 nocomment。v6 则删除了这两个选项。
如果想排除某些文件,可以使用选项 ignore 。
Windows
请在 glob 表达式里只使用斜杠。
译注:斜杠(forward-slashe “/“)是顺时针方向,反斜杠(backward-slashe “”)是逆时针方向。
尽管 Windows 可以用 / 或 \ 作为路径分隔符,但是本实现只使用 /。在 glob 表达式里必须只使用斜杠。反斜杠始终视为转义符,而不是路径分隔符。
绝对路径模式比如 /foo/*,匹配结果挂载到选项 root 设置的目录上(使用 path.join())。 在 Windows 下,在默认的情况下,/foo/* 可以匹配到 C:\foo\bar.txt(译注:此时 cwd 在 C 盘下)。
竞态条件
Glob 搜索本质上容易受竞态条件(race conditions)的影响,因为它建立在目录遍历等上面。
因此,当 glob 搜索某个文件时它是存在的,然后在返回结果时它可能被删除或被修改。
作为内部实现的一部分,为了降低系统开销,此实现缓存了所有的 stat 和 readdir 的结果。但是,这也导致它更加容易受竞态条件的影响,特别是在多个 glob 调用之间重用 cache 或 statCache 对象时。
在面对快速的变化时,建议用户不要将 glob 结果作为文件系统状态的担保。对于绝大多数的操作,这绝不会是一个问题。
贡献
对程序行为的任何改变(包含补丁)必须同时提交测试。
测试失败的或降低性能的补丁将被拒绝。
1 | # to run tests |