14

The ls can give a result like

[root@localhost ~]# cd /etc/yum.repos.d/
[root@localhost yum.repos.d]# ls

CentOS-Base.repo CentOS-Debuginfo.repo CentOS-Media.repo CentOS-Vault.repo

But actually I hope to just find out CentOS-Base.repoCentOS-Debuginfo.repo and CentOS-Vault.repo but not CentOS-Media.repo. So I run this command

ls [^\(Media\)]

But I get a error information.How should I do?

yode
  • 1,047

4 Answers4

12

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 -- *
    
11

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).

  • Why we cannot use ls *[^M]* – yode Jun 23 '17 at 12:00
  • The ls CentOS-[^M]* work,but the ls *[^M]* don't.. – yode Jun 23 '17 at 12:07
  • @yode, depends on what exactly you want to ignore: M character occurence OR Media word? – RomanPerekhrest Jun 23 '17 at 12:10
  • But in my case,only that file have a charater M. – yode Jun 23 '17 at 12:11
  • @yode, see my notation in the answer – RomanPerekhrest Jun 23 '17 at 12:17
  • Thanks your answer very very much,though I think the ls *[^M]* should work here still. – yode Jun 23 '17 at 12:38
  • 3
    The patterns are greedy: the first * matches everything except the last letter, the [^M] matches the last letter since none of them ends with M and the trailing * matches the empty string. So they all match. And even if something ended with M, it would still match, assuming there was something different from M somewhere: e.g. if you had a file called OOM, the first star would match the first O, the [^M] would match the second O and the trailing start would match the M. – NickD Jun 23 '17 at 12:49
8

The easiest way is to use find. Do:

find . -maxdepth 1 -type f ! -name "CentOS-Media.repo"

Here "f" means search for regular files only (excludes symlinks to regular files though; with GNU find, use -xtype f instead to include them). If you want to search for directories, pass "d" instead.

(-maxdepth while initially a GNU extension is now quite common. If your find doesn't support it, you can replace -maxdepth 1 with the standard ! -name . -prune).

see the find man page for more awesome features.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
6

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'

  • 1
    You can also get null-separated filenames with printf '%s\0' * which doesn't recurse and doesn't include dotfiles by default (but some shells have an option for that). You also don't need -E for that regexp, but to be picky you should either backslash the . or put it in [], and you do depend on GNU find and grep. – dave_thompson_085 Jun 23 '17 at 18:10