ls with numeric range doesn't work inside bash script

后端 未结 4 526
星月不相逢
星月不相逢 2020-12-21 07:03

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/         


        
相关标签:
4条回答
  • 2020-12-21 07:04

    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 $ 
    
    0 讨论(0)
  • 2020-12-21 07:07

    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
    
    0 讨论(0)
  • 2020-12-21 07:14

    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}")
    
    0 讨论(0)
  • 2020-12-21 07:31

    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
    
    0 讨论(0)
提交回复
热议问题