Shell globbing exclude directory patterns Shell globbing exclude directory patterns shell shell

Shell globbing exclude directory patterns


Michael's answer is right. ** matches too much (greedy match), including assets.

So, with this tree:

.|-- 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

The .js files are:

$ 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

There is a bash variable GLOBIGNORE to do exactly what you are trying to do.

So, this would work:

$ GLOBIGNORE='**/assets/**:assets/**:**/assets'$ ls -1 **/*.jsa/a2/a2.jsb/b1/b1-2/b1-2-3/test/test2/test3/test4/test4.jsb/b1/b1-2/b1-2-3/test/test.jsb/b.jsc/c.jsx.js


The problem is that ** matches too much or too little in your case. In particular, the ** preceding !(assets) will match a1/assets/, then !(assets) will match a1-1 and the following ** will match nothing, so that the overall match succeeds.

Consider this simplified example:

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

The first ls works as intended, the second does not.


This might be the perfect time for you to start using zsh :-) Removing matches is simply done with ~:

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