Shell globbing排除目录模式

时间:2016-06-01 06:37:12

标签: bash shell glob

忽略可以与shell globs关联使用的命令,我想完成从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

3 个答案:

答案 0 :(得分:3)

迈克尔的回答是正确的。 **匹配太多(贪婪匹配),包括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

答案 1 :(得分:1)

问题是**在您的情况下匹配太多或太少。特别是,**之前的!(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按预期工作,第二个不工作。

答案 2 :(得分:0)

这可能是您开始使用zsh的最佳时机:-)删除匹配只需使用~完成:

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