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 to x1y, x2y.... Copied by a few other shells since.
  • for var (values) cmd: short form of for 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 subtraction
  • print -l: print in lines

Tags:

Ls

Wildcards