How can I use $variable in a shell brace expansion of a sequence?
You may want to try :
eval rm foo.{$ext0..$extN}
Not sure whether this is the best answer, but it certainly is one.
As you already realized, {1..3}
expands to 1 2 3
but {foo..bar}
or {$foo..$bar}
don't trigger brace expansion, and the latter is subsequently expanded to replace $foo
and $bar
by their values.
A fallback on GNU (e.g. non-embedded Linux) is the seq
command.
for x in `seq $ext0 $extN`; do rm foo.$x; done
Another possibility. if foo.
contains no shell special character, is
rm `seq $ext0 $extN | sed 's/^/foo./'`
The simplest solution is to use zsh, where rm foo.{$ext0..$extN}
does what you want.
While the other answers discuss using eval
and seq
, in bash
, you can use a traditional C style for
loop in an arithmetic context. The variables ext0
and extN
are expanded inside the ((..))
causing the loop to run for the range defined.
for (( idx = ext0; idx <= extN; idx++ )); do
[[ -f "$foo.$idx" ]] || { printf "file %s does not exist" "$foo.$idx" >&2 ; continue ; }
rm "$foo.$idx"
done
If you are looking for an optimal way and avoid multiple rm
commands, you can use a temporary placeholder to store the filename results and call rm
in one-shot.
results=()
for (( idx = ext0; idx <= extN; idx++ )); do
[[ -f "$foo.$idx" ]] || { printf "file %s does not exist" "$foo.$idx" >&2 ; continue ; }
results+=( "$foo.$idx" )
done
and now call the rm
command on the expanded array
rm -- "${results[@]}"