簡體   English   中英

Shell globbing 排除目錄模式

[英]Shell globbing exclude directory patterns

忽略可以與 shell glob 關聯使用的命令,我想完成從 glob 模式中排除所有目錄和子目錄中的特定目錄模式。

假設我有這個目錄結構:

+-- a
    +-- a1
         +-- assets
                  +-- a1-1
                         +-- a1-1.js
                  +-- a1-2
                         +-- a1-2.js
    +-- a2
         +-- a2.js
+-- b
    +-- b1
         +-- b1-2
                +-- b1-2-3
                         +-- assets
                                  +-- b1-2-3.js
    +-- b.js
+-- c
    +-- c.js

我想列出文件路徑中沒有assets的所有 js 文件。

到目前為止我已經嘗試過:

$ shopt -s globstar extglob
$ ls ./**/!(assets)/**/*.js

上面的模式不僅實現了它的目標,它甚至顯示了重復的輸出。 我知道我可以做這樣的事情:

$ ls ./**/*.js | grep -v "assets"

或者任何其他可以通過管道傳輸的命令,我只想要一個純 shell glob 模式。

預期輸出:

a/a2/a2.js  
b/b.js  
c/c.js

邁克爾的回答是對的。 **匹配太多(貪婪匹配),包括assets

所以,有了這棵樹:

.
|-- a
|   |-- a1
|   |   +-- assets
|   |       |-- a1-1
|   |       |   +-- a1-1.js
|   |       +-- a1-2
|   |           +-- a1-2.js
|   +-- a2
|       +-- a2.js
|-- assets
|   +-- xyz.js
|-- b
|   |-- b1
|   |   +-- b1-2
|   |       +-- b1-2-3
|   |           |-- assets
|   |           |   +-- b1-2-3.js
|   |           +-- test
|   |               |-- test2
|   |               |   +-- test3
|   |               |       +-- test4
|   |               |           +-- test4.js
|   |               +-- test.js
|   +-- b.js
|-- c
|   +-- c.js
+-- x.js

.js 文件是:

$ find . -name '*.js'
./x.js
./assets/xyz.js
./a/a2/a2.js
./a/a1/assets/a1-2/a1-2.js
./a/a1/assets/a1-1/a1-1.js
./c/c.js
./b/b.js
./b/b1/b1-2/b1-2-3/test/test2/test3/test4/test4.js
./b/b1/b1-2/b1-2-3/test/test.js
./b/b1/b1-2/b1-2-3/assets/b1-2-3.js

有一個 bash 變量GLOBIGNORE可以完全按照您的要求進行操作。

所以,這會起作用:

$ GLOBIGNORE='**/assets/**:assets/**:**/assets'
$ ls -1 **/*.js
a/a2/a2.js
b/b1/b1-2/b1-2-3/test/test2/test3/test4/test4.js
b/b1/b1-2/b1-2-3/test/test.js
b/b.js
c/c.js
x.js

問題是**在您的情況下匹配太多或太少。 特別是!(assets)前面的**將匹配a1/assets/ ,然后!(assets)將匹配a1-1 ,后面的**將不匹配任何內容,因此整體匹配成功。

考慮這個簡化的例子:

touch a/a1/x.js a/a2/y.js a/a3/z.js
ls ./*/!(a2)/*.js
ls ./**/!(a2)/**/*.js

第一個ls按預期工作,第二個沒有。

這可能是您開始使用zsh的最佳時機 :-) 只需使用~即可刪除匹配項:

% setopt extended_glob
% ls -1 **/*.js~*assets*
a/a2/a2.js
b/b.js
c/c.js

如果這是您經常搜索的內容,那么我只會編寫一個簡單的腳本。

對於測試,設置文件和目錄,如問題中所述:

(注意添加 c/assets.js 來測試邊緣案例)

mkdir -p a/a1/assets/a1-1 a/a1/assets/a1-2 a/a2 b/b1/b1-2/b1-2-3/assets c
touch a/a1/assets/a1-1/a1-1.js a/a1/assets/a1-2/a1-2.js a/a2/a2.js b/b1/b1-2/b1-2-3/assets/b1-2-3.js b/b.js c/c.js
touch c/assets.js

劇本:

#!/bin/bash

shopt -s globstar  # enable ** to recurse all the directories

files=()  # create array variable

for f in **/*.js; do  # glob pattern match all .js files
  if [[ ! "$f" =~ "assets/" ]]; then  # regex match all paths that do NOT contain an 'assets' directory
    files+=("$f")  # add it to the files array
  fi
done

printf %s\\n "${files[@]}"  # print the files array

結果:

a/a2/a2.js
b/b.js
c/assets.js
c/c.js

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM