I’m trying to get something like ls **/*!(test).rb to expand to all ruby files which do not end with “test”. However, everything I tried so far didn’t help. I tried turning on ZSH’s expanded globbing option, but no luck.

I know could just do something like ls -l **/*.rb | grep -v test but I’d really like to do it with globbing only


1 Answer 1

setopt extended_glob; ls -d -- **/(^*test).rb


setopt ksh_glob; ls -d -- **/!(*test).rb

The different form from your version (*!(test).rb) will also match foo-test.rb, because the * matches the foo-test part of the filename, and the !(test) negation matches the empty string.

The "ksh-glob" form also works in bash, with shopt -s globstar extglob:

#! /bin/bash
shopt -s globstar extglob
ls -d -- **/!(*test).rb

Notice that in bash there should be a newline between shopt -s extglob and the use of an extended pattern, and the two may not be part of the same compound command or function.

  • The first one just matched everything like **/* would but the ksh version worked perfectly! Thank you so much :) Sep 15, 2019 at 15:12
  • what version of zsh are you using? could try a simpler testcase like this: zsh -c 'mkdir -p /tmp/a/b/c/d && cd /tmp/a && touch b/{{f,f-test}.rb,c/{f,f-test}.rb} && setopt extended_glob && ls **/(^*test).rb'
    – mosvy
    Sep 15, 2019 at 15:24

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.