4

Given this directory content :

one.file
two.file
three.file

in bash, when I enter

rm *.file !(two)

only one.file and three.file are deleted. How can I do this in ZSH?

  • 3
    In fact, you need to use rm !(two).file in bash. – choroba Jun 27 '14 at 15:17
7

I was interested in the answer too, and a quick search turned up this article on globbing in zsh. The highlights:

  • ^ Acts as a negation. For example, ls ^two.file will only list the one.file and three.file.
  • You can combine ^ and *. For example, ls ^two* will list anything that doesn't start with "two"
  • You can use parentheses to make more complex matches. For example, ls (^two).file will list anything that doesn't start with "two", and does end in "file".
  • 4
    Enable extended globbing first: setopt extended_glob – Emre Sep 19 '15 at 1:12
  • @Emre Thanks a lot, that was the one info that took me 2 hours to find – Luke Nov 22 '15 at 1:33
3

If you want to use the ksh syntax ls !(two).file, simply turn on the KSH_GLOB option in zsh:

$ setopt KSH_GLOB
$ ls -1 !(two).file
one.file
three.file

But zsh provides other powerful globbing techniques, activated by the EXTENDED_GLOB option. For a complete list, please read the section FILENAME GENERATION in man zshexpn. Most relevant to the question are these operators:

  • ^x matches anything except the pattern x, so in your case ls -1 ^two.file
  • x~y is more powerful as it matches anything that matches the pattern x but does not match y, so ls -1 *~two.file. The special thing is, that you have can use another globbing pattern for x, e.g.

    $ ls -1 *.file~two*
    one.file
    three.file
    

    This is not possible with the ^ operator, which is in this case equivalent to *~:

    $ ls -1 *.file^two*
    one.file
    three.file
    two.file
    

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.