0

I have a list of files to put through a for loop. They are named

FA2_00032.png, FA2_00033.png, etc

I have variables $imID which contains FA2 string, $startFrame which contains the start frame (e.g. 00034) and $endFrame which contains to end frame (e.g. 00894).

I have managed to get the list of relevant files using:

eval echo ${imageID}_{${startFrame}..${endFrame}}.png;

This outputs

FA2_00034 FA2_00035 FA2_00036 etc

But now I need to pass this to the for loop. That is,

for file in *the above list*

where *the above list* is the block quoted list above. $file should contain FA2_00034, FA2_00035, etc for use in the for loop.

codeforester
  • 39,467
  • 16
  • 112
  • 140
TCS
  • 1
  • 1
  • BTW, this is [BashPitfalls #33](http://mywiki.wooledge.org/BashPitfalls#for_i_in_.7B1...24n.7D) – Charles Duffy Apr 23 '18 at 16:12
  • 1
    Beware, there are some bad answers in the linked duplicate. – chepner Apr 23 '18 at 16:13
  • @CharlesDuffy, @chepner: what do you think of using `xargs` for this? (eg. `seq ${startFrame} ${endFrame} | xargs -I {} printf "%s_%05d.png\\n" ${imageID} {}`). Seems like a nice way without using a loop. – l'L'l Apr 23 '18 at 16:57
  • @l'L'l, `seq` is neither part of bash nor part of the POSIX spec. It's not guaranteed to be available, nor to have any particular behavior when it *is* present. And `xargs printf`, using `/usr/bin/printf`, is much more expensive than using the `printf` shell builtin. – Charles Duffy Apr 23 '18 at 17:03
  • @CharlesDuffy: Interesting, I didn't realize the `xargs` was actually using it's own `printf` — thank you for the reply/advice/tips as always! – l'L'l Apr 23 '18 at 17:08
  • It's more that the shell provides a builtin printf, but as an external executable xargs can't directly call shell builtins, so unless you do something that starts a shell, like `xargs sh -c 'printf "$0" "$@"' 'FA2_%05d.png\n'`, it has to use the external implementation from the PATH -- so less xargs doing something special, and more the shell doing something special. – Charles Duffy Apr 23 '18 at 17:18

1 Answers1

1

Use a C-style for loop, not eval+{...}, for tasks like this. printf can be used to assemble the file name from the current integer. The syntax 10#$foo ensures that the value of $foo is treated as a decimal (not an octal) number if it includes leading 0s.

imageID=FA2
startFrame=00034
endFrame=00894

for ((i=10#startFrame; i<=10#$endFrame; i++)); do
    printf -v file '%s_%05d.png' "$imageID" "$i"
    echo "Operating on $file" >&2
done
chepner
  • 497,756
  • 71
  • 530
  • 681