I'm trying to ls dirs that have .png files inside (no need for recursiveness, though it would be extra useful), exept one. Exlude one directory i.e.

ls */*.png

works fine.

ls (^one)*/*.png

returns no stdout. How do I achieve it?

I am blind and piping it to espeak, so I can only hear stdout for now.

  • Which shell are you using? Your pattern looks like a zsh pattern, though not a useful one as it wouldn't exclude one (the right pattern would be ^one/*.png), it would print everything. – Gilles 'SO- stop being evil' Apr 25 '15 at 12:55

Option 1 - using just ls:
With extended bash globbing turned on (shopt -s extglob) you can do:

ls !(one*)/*.png

Option 2 - combining ls and grep:

You can combine ls with grep -v

  • e.g. ls */*.png | grep -v "one/"

Option 3 - (the best IMO) but uses find not ls:

For recursive searching of all subdirectories using find

find . -type f -name "*.png" -not -path "*/one/*"

All of the above one-liners will list directories with .png files while filtering out any path matching one/; only Option 3 will do this recursively.

  • Doesn't the find command need to say -path "*/one/*" or -path "./one/*"? – G-Man Says 'Reinstate Monica' Apr 25 '15 at 3:02
  • @G-Man You're absolutely right. Edited above. – toxefa Apr 25 '15 at 8:05
  • Wouldn't that still match ./phone/handset.png? – G-Man Says 'Reinstate Monica' Apr 25 '15 at 8:07
  • @G-Man What's wrong with matching .pngs in a directory called phone? I thought we were just trying to exclude one? – toxefa Apr 25 '15 at 8:09
  • 1
    Well, since you're using it in connection with -not, it means that it causes the find to exclude files in a directory called phone. – G-Man Says 'Reinstate Monica' Apr 25 '15 at 8:13

In zsh, put setopt extended_glob in your ~/.zshrc. Then you can use the wildcard pattern ^one to exclude the directory called one.

ls ^one/*.png

If you want to recurse into subdirectories, use **/ for recursive globbing. To exclude the directory called one at the toplevel, as well as the toplevel directory:

ls ^one/**/*.png

To exclude files in a subdirectory called one, but not files in subdirectories of it:

ls **/^one/*.png

To exclude files under a subdirectory called one at any level, use a repeat pattern with the # operator around the negation:

ls (^one/)#/*.png

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.