I am having much difficulty with this. I am trying to test if there exists files in a directory that DO NOT match a given pattern, returning true or false.
In this case, files in $dir
that don't start with an underscore, _
.
I figured I would try if [ -f $dir/!(_*) ]
, if [ $dir -f -name ! _* ]
or
if ls $dir/!(_*) 1> /dev/null 2>&1
but it would always say Too many arguments
or syntax error near unexpected token "("
Best Answer
Or, for
/bin/sh
(andbash
for that matter):In short, expand the appropriate globbing pattern and test whether it matched something that exists.
The
[!_]
pattern will match any character that is not an underscore. It is similar to the regular expression[^_]
, but filename globbing patterns use!
instead of^
to negate a character class.When the pattern doesn't match, by default, it will remain unexpanded, so that's why we use the
-e
test to make sure the first thing in the match list exists. We can't really test the length of the returned list because if the length is 1, it still may have matched nothing (unless you have thenullglob
shell option set inbash
).It becomes a tiny bit trickier if you want to test for regular files specifically, since globbing patterns matches any name (directories, regular files, and all other types of files). But this would do it:
Or, for
/bin/sh
:This approach would also detect a symbolic link to a regular file whose name does not start with an underscore.
The looping is necessary to shift off any names of files that are not regular files (e.g. directory names) that we may have matched.
In the
zsh
shell, you could use the pattern"$dir"/[^_]*(.)
which is guaranteed to only match regular files (if it matches anything).For more complex patterns, you could naively compare the number of items matched with the number of items matched by
*
. If they differ, there are names that does not match the complex pattern.In
bash
, you may use the extended globbing pattern!(PATTERN)
after enabling theextglob
shell option withshopt -s extglob
. The general form is!(pattern1|pattern2|pattern3|etc)
. You would still have to examine the result of the expansion as above to see whether it expanded to anything.The example with names not starting with an underscore may use the
!(_*)
extended globbing pattern, but note that!(_)*
would not work as that would match every visible name, just like*
would.