13

Let's say I have a directory with files a1, a2, a3, b1, b2, b3. I only want to match files that start with a but don't contain 3. I tried ls -I "*3" *a* but it returns a1 a2 a3, even though I don't want it to match a3. Is this possible with ls?

2
  • interesting diverse set of answers here, but an explanation of why ls -I '*3' a* fails would be edifying. and/or why is the shell's globbed list not being subsequently filtered by the ignore switch to ls? Commented Oct 21, 2015 at 20:53
  • The man page says about the -I option: do not list implied entries matching shell PATTERN, however it doesn't explain what is meant by implied, but I'm guessing it only applies to files that ls gets by glob expansions - and ls doesn't expand the a*, the shell does that. Commented Oct 24, 2015 at 1:09

5 Answers 5

14

Just:

shopt -s extglob failglob
ls -d a!(*3*)
  • shopt -s extglob activates extended globbing (enables a subset of ksh's extended operators).
  • failglob it to cancel the command if there's no match rather than calling it with the glob pattern left as is. Without it, that could end up list the file called a!(*3*) even though it contains a 3.
  • a matches the starting a
  • !() negates the match inside the ()...
  • *3* which is 3 and anything before or after it.

$ touch 1 2 3 a1 a2 a3 b1 b2 b3 aa1 aa2 aa3 a2a a3a
$ ls -d a!(*3*)
a1  a2  a2a  aa1  aa2
0
8

Existing answers well state the best way to do this with globs; I'll include this because in most cases, find is a better option if you want to do scripting or further processing:

$ find . -maxdepth 1 -name 'a*' -not -name '*3*'
./a1
./a2

You can feed the answer to xargs for easy actions, or to a while read loop for more complicated things.

1
  • See ! for the standard equivalent to -not. Note that in order to be able to feed it to xargs or read, you need to add a -print0 and use xargs -r0 or whilte IFS= read -rd '' file (for which you need zsh or bash) Commented Mar 17, 2023 at 12:40
3

An easy way is

  • to list all files that match a*
  • then delete all lines containing a 3

The UNIX command is

ls -1 a* | grep -v 3

ls -1 shows one file per line.

grep normally finds lines that match a pattern but with -v this behaviour is inverted, i.e. grep finds line that don't match that pattern.

2
  • 2
    Hi Peter! It would be best to explain, in as much detail as is relevant, how your solution works.
    – dhag
    Commented Oct 21, 2015 at 19:35
  • 3
    Parsing ls is not a goob idea: mywiki.wooledge.org/ParsingLs
    – chaos
    Commented Oct 21, 2015 at 19:38
3

With zsh, using the ~ glob operator:

setopt extendedglob
print -rl -- a*~*3*

With gnu ls you could use two --ignore options:

ls -I '[^a]*' -I '*3*'

the 1st ignores all file names that don't start with a and the 2nd ignores file names that contain 3

0

As answers before suggest: Yes, it is possible to solve this with ls. To me, this particular question also somewhat implies why your solution has not worked out. Therefore, I'd like to give a late contribution on that.
Basically,

ls -I "*3" *a*

asks to exclude all entries ending in 3, but in turn includes explicitly all files containing an a. In fact, *a* uses shell globbing and is expanded before the actual command is executed (this does not apply to "*3" as this part is quoted). Thus, your command is in your case equivalent to

ls -I "*3" a1 a2 a3

consequently listing the entry a3. Thus, explicit given entries to be listed are overruling entries concerned by -I. From there, I derive, implicitly in the sense of the manual means everything not specified explicitly, e.g.

ls -I "*3"

would have excluded a3 (but shown other considered entries in that directory too, e.g. b1).

2
  • Hey @Peregrino69, thanks for your remark. As you figured, I cannot yet comment. On the other side, I found, this explanation is an important addition to answering the question. I have precised this now. Commented Mar 17, 2023 at 10:40
  • Agreed mate :-) However Q&A sites work differently from discussion forums. An answer should be self-contained; i.e. if everyone else decides to delete theirs, the OP (or anyone stumbling upon this via web search) should be able to resolve the issue just with your answer alone. Same logic applies here as with links to external sources - link-only answers do get deleted. Check the Tour and the Asking and Answering -sections in the Help center; that'll give a good understanding on how these sites work. Commented Mar 17, 2023 at 11:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .