Is it possible to achieve the following with a simple ls command using bash.
List all the files that begin with two letters, have an e in the name and end with 1 or more letter.
If so, what is the command and does extended globbing need to be enabled ?
- 544,893
- 31
1 Answers
ls doesn't match file names (unless you want to consider GNU extensions like --include/--exclude). It's the shell globs that are typically used for that.
ls -ld [[:alpha:]][[:alpha:]]*e*[[:alpha:]]
would find files that match those requirements, but would miss ee for instance. You could do:
zsh
Using the AND NOT/EXCEPT operator (~) and NOT (^):
setopt extendedglob
ls -ld [[:alpha:]](#c2)*~^*e*~^*[[:alpha:]]
Or using perl-like look ahead regular expression operators:
setopt rematchpcre
match() [[ $REPLY =~ '^(?=.*e)(?=.*[[:alpha:]]$)[[:alpha:]][[:alpha:]]' ]]
ls -ld *(+match)
ksh93
Using & inside @(...):
ls -ld @([[:alpha:]][[:alpha:]]*&*e*&*[[:alpha:]])
Same with its augmented regexps (enabled with ~(X:...)):
ls -ld ~(X:[[:alpha:]][[:alpha:]].*&.*e.*&.*[[:alpha:]])
Or using perl-like look-ahead operators:
ls -ld ~(P:(?=.*e)(?=.*[[:alpha:]]$)[[:alpha:]][[:alpha:]])*
bash
bash has no AND operator but it does support a subset of ksh's operators when the extglob option is enabled, so you could do things like:
shopt -s extglob
ls -ld @([[:alpha:]]?([[:alpha:]]*)e?(*[[:alpha:]])|e[[:alpha:]]?(*[[:alpha:]]))
@(x|y) (like zsh's (x|y)) is a OR operator. ?(x) is an optional x (like zsh's (x|); @(x|) would also work for that in ksh/bash).
Another trick is to use the fact that "A and B" is "not(not(A) or not(B))", and the subset of ksh globs supported by bash so happens to include a not and or operators so you can do:
ls -ld !(!([[:alpha:]][[:alpha:]]*)|!(*e*)|!(*[[:alpha:]]))
Those ones would also work in ksh (all variants, no shopt there) where those operators come from in the first place.
Non-glob-based approaches
With find:
find . ! -name . -prune -name '[[:alpha:]][[:alpha:]]*' \
-name '*e*' \
-name '*[[:alpha:]]' -exec ls -ld {} +
(beware the file list won't be sorted and file names containing bytes that don't form valid characters will be excluded; file names will also be prefixed with ./).
- 544,893
-
-
@damiant, which command? In which shell? And in which way does it not work? – Stéphane Chazelas Oct 06 '17 at 19:35
-
the bash command. i was trying with ls | grep “^[a-zA-Z][a-zA-Z].e.[a-zA-Z]$” but that wont work if either of the first 2 characters are e – damiant Oct 06 '17 at 20:32
-
@damiant what file name does that
ls -ld @([[:alpha:]]?([[:alpha:]]*)e?(*[[:alpha:]])|e[[:alpha:]]?(*[[:alpha:]]))bashcommand fail to match or fail to not-match. For me it correctly matchesee,eea,ee1aand correctly fails to matchee1,eee1andee11– Stéphane Chazelas Oct 06 '17 at 21:03
ls [a-zA-Z][a-zA-Z]*e*[a-zA-Z][a-zA-Z]. No. http://idownvotedbecau.se/noattempt/ – blafasel Oct 06 '17 at 11:51ls [a-zA-Z][a-zA-Z]*e*[a-zA-Z]should also list "banker". – blafasel Oct 06 '17 at 12:27