8

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?

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

2 Answers 2

12

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".
3
  • 7
    Enable extended globbing first: setopt extended_glob
    – Emre
    Sep 19, 2015 at 1:12
  • @Emre Thanks a lot, that was the one info that took me 2 hours to find Nov 22, 2015 at 1:33
  • @LukasJuhrich lol, you're not alone. Jun 18, 2022 at 10:37
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
    

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .