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:]]))
bash
command fail to match or fail to not-match. For me it correctly matchesee
,eea
,ee1a
and correctly fails to matchee1
,eee1
andee11
– 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