How can I use wildcards with ls to find files that are missing in a numeric sequence?
ls *{369..422}*.avi >/dev/null
This will first generate patterns like
*369*.avi
*370*.avi
*371*.avi
*372*.avi
*373*.avi
*374*.avi
through the brace expansion, and then ls
will be executed with these patterns, which will give you an error message for each pattern that can't be expanded to a name in the current directory.
Alternatively, if you have no files that contain *
in their name:
for name in *{369..422}*.avi; do
case "$name" in
'*'*) printf '"%s" not matched\n' "$name" ;;
esac
done
This relies on the fact that the pattern remains unexpanded if it did not match a name in the current directory. This gives you a way of possibly doing something useful for the missing files, without resorting to parsing the error messages of ls
.
If you want *numbers*.avi
, you can do:
ls *[0-9]*.avi
The [0-9]
specifies a character class consisting of all characters between 0
and 9
in your locale. That should be all numbers. So you want to match 0 or more characters (*
), then a number [0-9]
and then 0 or more characters again (*
).
If you need to have more than one number in sequence, use:
ls *[0-9][0-9]*.avi
Finally, if you have files in numerical order and just want to find the missing ones, you could also write a little loop:
for avi in {369..422}.avi; do [ -e "$avi" ] || echo "$avi missing"; done
To list which of the *{369..422}*.avi
patterns don't match any file, with zsh
, you could do:
for p (\*{369..422}\*.avi) () {(($#)) || echo $p} $~p(N[1])
Or more verbosely:
for p (\*{369..422}\*.avi) () {
if (($#)); then
echo "$# file(s) matching $p"
else
echo >&2 No file matching $p
fi
} $~p(N)
For files following a fixed pattern like: foo-123-bar.avi
, you can also do:
expected=(foo-{369..422}-bar.avi)
actual=($^expected(N))
missing=(${expected:|actual})
print -l $missing
Some of the zsh
-specific features in there:
x{1..20}y
brace expansion expanding tox1y
,x2y
.... Copied by a few other shells since.for var (values) cmd
: short form offor
loop() compound-command args
: anonymous function like in many other languages.$~p
: treat the content of$p
as a glob (other shells do that by default, and even word splitting!)(N[1])
: glob qualifier for globs to expand to no argument when they don't match any file.[1]
select the first matching file only as we only one to tell whether there has been any match.$^array
: brace-like expansion for the elements on an array${array1:|array2}
: array subtractionprint -l
: print in lines