How to find all files except a specified file

A few shells have negation globbing operators:

  • zsh -o extendedglob:

    ls -d -- ^*Media*
    ls -d -- *.repo~*Media* # ~ is "except" operator
    
  • ksh, zsh -o kshglob, bash -O extglob:

    ls -d -- !(*Media*)
    
  • bash:

    GLOBIGNORE='*Media*'
    ls -d -- *
    
  • ksh:

    FIGNORE='@(*Media|.)*'
    ls -d -- *
    

In most simple case you may use the following (in case if the 1st subword is static CentOS):

ls CentOS-[BDV]*

  • [BDV] - character class to ensure the second subword starting with one of the specified characters

or the same with negation:

ls CentOS-[^M]*

If you want to ignore all filenames that contain the M character, with the GNU implementation of ls (as typically found on CentOS), use the -I (--ignore) option:

ls -I '*M*'

-I, --ignore=PATTERN
do not list implied entries matching shell PATTERN

To ignore entries with Media word:

ls -I '*Media*'

Those patterns need to be passed verbatim to ls, so must be quoted (otherwise, the shell would treat them as globs to expand).


One option is to use find with the -not -name flags. I.e. find . -not -name CentOS-Media.repo. If you don't want to recurse down the directory structure, add -maxdepth 1 flag.

Alternatively, one may write the following (which is much more complex, but I forgot about -not flag and posted this answer originally, so I will not delete this part):

find . -print0 | grep --invert-match -z "CentOS-Media.repo$" | tr '\0' '\n'

You need to force find to separate filenames with null byte, so that newlines in filenames won't break anything down. Hopefully, grep supports this kind of separator with flag -z. You may want to revert to the typical separation (i.e. null byte -> new line) with tr '\0' '\n'

Tags:

Wildcards