原文地址:github.com/isLishude/b…javascript
本文 由 Ivan Yan 翻譯,"署名-非商用-相同方式共享",意見反饋。java
經過星號等 shell 所用的模式匹配文件。node
這是一個 JavaScript 版本的 glob 實現。使用 minimatch 執行匹配操做。git
譯註:早期 Unix (第 1-6 版,1969-1975)的命令行解釋器依賴獨立程序 /etc/glob 展開參數中的通配符。這個程序會展開通配符並把展開後的文件列表傳給命令。它的名字是 "global command" 的簡稱。後來這個功能由工具函數 glob() 提供,被 shell 等程序使用。(譯自 WikiPedia。)github
用 npm 安裝:正則表達式
npm i glob
複製代碼
var glob = require("glob")
// options 可選
glob("**/*.js", options, function (er, files) {
// files 是一個文件名數組。
// 若是設置了選項 `nonull` 而且沒有找到匹配,則 files 是 ["**/*.js"]
// er 是一個錯誤對象或 null。
})
複製代碼
"Globs" 是像這樣的模式:用在命令行中的 ls *.js
, 用在 .gitignore
文件中的 build/*
。shell
在解析路徑中的模式前,先展開大括號部分。大括號部分以 {
開始,以 }
結束,裏面是一個逗號分隔列表。大括號部分能夠包含斜槓,例如 a{/b/c,bcd}
將展開爲 a/b/c
與 abcd
。npm
譯註:好比路徑 "/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 會返回模式。例如:
$ echo a*s*d*f
a*s*d*f
複製代碼
想與 shell 一致,設置選項 nonull:true
。
man sh
man bash
(搜索 "Pattern Matching")man 3 fnmatch
man 5 gitignore
若是模式包含特殊的字符則返回 true
,不然返回 false
。
注意選項會影響結果。若是設置了選項 noext:true
,則 +(a|b)
不會視爲魔法模式。若是模式包含大括號展開式,好比 a/{b/c,x/y}
,則認爲是魔法的,除非設置了選項 nobrace:true
。
pattern
{String}
待匹配的模式options
{Object}
cb {Function}
err
{Error | null}
matches
{Array<String>}
匹配模式的文件名進行一個異步的 glob 搜索。
pattern
{String}
待匹配的模式options
{Object}
{Array<String>}
匹配模式的文件名進行一個同步的 glob 搜索。
實例化 glob.Glob
類,建立一個 Glob 對象。
var Glob = require("glob").Glob
var mg = new Glob(pattern, options, cb)
複製代碼
這是一個 EventEmitter 對象,馬上開始遍歷文件系統搜索匹配。
pattern
{String}
待匹配的模式
options
{Object}
cb {Function}
當遇到錯誤或找到匹配時調用
err
{Error | null}
matches
{Array<String>}
匹配模式的文件名注意,若是設置了選項 sync
,則匹配將當即添加到 g.found
。
minimatch
glob 所用的 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 操做將由於共享文件系統的信息而提速。
cwd
String,搜索的工做目錄,默認爲 process.cwd()
。root
String,以 /
開始的模式的掛載目錄,默認爲 path.resolve(options.cwd, "/")
(Unix 系統下爲 /
,Windows 系統下爲 C:\
或其它磁盤根目錄。)dot
在常規匹配與 globstar
匹配中包含點文件。注意,.
在模式片段中始終匹配點文件。nomount
以 /
開始的模式默認掛載到 root 選項設置的目錄上,於是返回一個合法的文件系統路徑。設置此選項禁止此行爲。mark
給匹配的目錄添加一個 /
字符。注意這會調用 stat
。nosort
不排序結果。stat
stat 全部的結果。這多少會下降性能,徹底不必,除非認爲 readdir
不能做爲文件存在的可靠指示。silent
當讀取目錄時遇到一個不常見的錯誤,將打印一條警告到 stderr。設置此選項可取消打印。strict
當讀取目錄時遇到一個不常見的錯誤,進程將繼續搜索其它匹配。設置此選項可拋出錯誤。cache
Object, 見上文。傳入以前生成的緩存對象能夠節省一些 fs 調用。statCache
Object, 匹配結果的文件系統信息的緩存,用來阻止沒必要要的 stat
調用。一般不須要設置此選項。不過若是知道文件系統在不一樣的 glob() 調用之間不會變化,能夠將一個 glob() 調用的 statCache 傳給另外一個調用的選項(見下面「競態條件」)。symlinks
Object, 已知的符號連接的緩存。能夠傳入一個以前生成的 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
事件的返回值。嚴格地兼容現實規範是值得追求的目標,不過 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
。
請在 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 結果做爲文件系統狀態的擔保。對於絕大多數的操做,這毫不會是一個問題。
對程序行爲的任何改變(包含補丁)必須同時提交測試。
測試失敗的或下降性能的補丁將被拒絕。
# to run tests
npm test
# to re-generate test fixtures
npm run test-regen
# to benchmark against bash/zsh
npm run bench
# to profile javascript
npm run prof
複製代碼
關注公衆號,發現更多精彩