I have a folder with files named as file_1.ext...file_90.ext
. I can list a range of them with the following command:
$ ls /home/rasoul/myfolder/
Numeric ranges have to be literal numbers, you can't put variables in there. To do it you need to use eval
:
FILES=`eval "ls ${DIR}/file_{$st..$ed}.ext"`
Here's a transcript of my test (I tried it in bash 4.1.5 and 3.2.48).
imac:testdir $ touch file_{1..30}.ext
imac:testdir $ st=6
imac:testdir $ ed=20
imac:testdir $ DIR=.
imac:testdir $ FILES=`eval "ls ${DIR}/file_{$st..$ed}.ext"`
imac:testdir $ echo "$FILES"
./file_10.ext
./file_11.ext
./file_12.ext
./file_13.ext
./file_14.ext
./file_15.ext
./file_16.ext
./file_17.ext
./file_18.ext
./file_19.ext
./file_20.ext
./file_6.ext
./file_7.ext
./file_8.ext
./file_9.ext
imac:testdir $
Brace expansion happens before variable expansion.
(Moreover, don't parse ls output.). You could instead say:
for f in $(seq $st $ed); do
echo "${DIR}/file_${f}.ext";
done
The range pattern {A..B}
does not accept variables for A
or B
. You need constants for them.
A workaround might be to start a subshell like this:
RESULT=$(bash -c "ls {$a..$b}")
BASH
always does brace expansion
before variable expansion
which is why ls
is looking for a file /home/rasoul/myfolder/file_{6..19}.ext
.
I personally use seq
when I need to expand a number range that has variables in it. You could also use eval
with echo
to accomplish the same thing:
eval echo {$st..$ed}
But even if you used seq
in your script, ls
would not iterate over your range without a loop. If you want to check if files in the range exist, I would also avoid using ls
here as you will get errors for every file in the range that doesn't exist. BASH
can check if a file exists using -e
.
Here is a loop that would check if a file exists within the range between variables $st
and $ed
and print it if it does:
for n in $(seq $st $ed); do
f="${DIR}/file_$n.ext"
if [ -e $f ]; then
echo $f
fi
done