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?
-
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? – Theophrastus Oct 21 '15 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. – Murray Jensen Oct 24 '15 at 01:09
5 Answers
Just:
shopt -s extglob failglob
ls -d a!(*3*)
shopt -s extglobactivates extended globbing (enables a subset of ksh's extended operators).failglobit 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 calleda!(*3*)even though it contains a3.amatches the startinga!()negates the match inside the()...*3*which is3and 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
- 522,931
- 91
- 1,010
- 1,501
- 47,463
- 11
- 118
- 144
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.
- 9,808
- 4
- 25
- 43
-
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) – Stéphane Chazelas Mar 17 '23 at 12:40
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.
-
2Hi Peter! It would be best to explain, in as much detail as is relevant, how your solution works. – dhag Oct 21 '15 at 19:35
-
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
- 79,330
- 30
- 216
- 245
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).
- 1
- 1
-
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. – JonasKonrad Mar 17 '23 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](https://unix.stackexchange.com/tour) and the Asking and Answering -sections in the [Help center](https://unix.stackexchange.com/help); that'll give a good understanding on how these sites work. – Peregrino69 Mar 17 '23 at 11:10