zsh: excluding files from a pattern
Solution 1
You need to include the directory into the exception: print -l foo/*~foo/type_A*
or print -l foo/*~{foo/type_A*}
.
If you want, you can replace the directory by a wildcard:
print -l foo/*~*/type_A*
Solution 2
zsh has the ^
glob operator when EXTENDED_GLOB is on. It seems like the perfect fit for your stated situation:
setopt extendedglob
print -rl foo/^type_A*
It means “match anything, except what matches the following pattern”, but its effect is limited to the portion of the pattern between slashes, or between the beginning of the pattern and the first slash, or (as in this case) between the last slash and the end of the pattern.
You can view the zsh options currently enabled with:
setopt
And disable EXTENDED_GLOB with:
unsetopt extendedglob
Related videos on Youtube
Amelio Vazquez-Reina
I'm passionate about people, technology and research. Some of my favorite quotes: "Far better an approximate answer to the right question than an exact answer to the wrong question" -- J. Tukey, 1962. "Your title makes you a manager, your people make you a leader" -- Donna Dubinsky, quoted in "Trillion Dollar Coach", 2019.
Updated on September 18, 2022Comments
-
Amelio Vazquez-Reina over 1 year
Say I have the following files:
|-- bar `-- foo |-- type_A_1 |-- type_A_2 |-- type_B_1 |-- type_B_2 |-- type_B_xx |-- type_B_xx `-- something_else
I thought the following command
print -l foo/*~{type_B*}
would print everything under
foo
except things that start withtype_B
but it doesn't, instead it prints everything under foo:foo/type_A_1 foo/type_A_2 foo/type_B_1 foo/type_B_2 foo/type_B_xx foo/something_else
I also tried
print -l foo/*~type_B
and got the same thing.How does the exception wildcard
~
work in zsh? -
Amelio Vazquez-Reina over 12 yearsThanks! About the second pattern, do you mind explaining how the pattern
foo/*~*/type_A*
works? Does the second*
expand to every folder under the working directory, or is it smart enough to only expand tofoo
? -
YoloTats.com over 12 years@roseck Because it seems really fast (for example when you run
print *~**/*
in the/
directory), I assume that it first expand the first pattern and then remove all matches which fit to the exclusion pattern. -
Gilles 'SO- stop being evil' over 12 years@roseck
~
is purely textual, the part before the~
expands as it always would, then the part after strips away matches. @jofel A better test would beprint /**/*~*
: you can observe that it traverses the whole tree, even if it ends up printing nothing. -
Geoffrey over 6 yearsI thought he wanted to exclude type_B but include type_A.
-
aryndin over 5 yearsRight answer is below
-
piojo over 3 yearsThe part after the ~ is not purely textual, but the ~ is the lowest precedence operator within the command (any single command, actually). That means the left half is evaluated, then the right half, then filtering is done. The ^ operator can be used for individual path components, but it is unary "not" rather than set subtraction.