2

This question already has an answer here:

I have a bash script like:

files="${@:2}"
for f in $files; do
  echo $f
done

which takes the shell expansion from the second argument to the last, and print it. However it does not work with files with spaces. It prints files:

test image.jpg

as

test
image.jpg

If I use:

for f in "${@:2}"; do
  echo $f
done

without assigning it to $files, it works fine.

I also tried to use the first case with quoted "$files", and does not work. It prints all files in one line. How can I assign the file names to another variable, while still making it work when using expansion like for in loop?

marked as duplicate by Gilles 'SO- stop being evil' bash Oct 11 '15 at 21:38

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • tried using "${files}"? – mkc Oct 11 '15 at 19:19
  • @Ketan it prints all file names in one line – texasbruce Oct 11 '15 at 19:19
  • in that case you need to add a new line in echo. Try using printf in place of echo: printf "$f\n" – mkc Oct 11 '15 at 19:20
  • 1
    @Ketan Try it please. It does not work as you think. – texasbruce Oct 11 '15 at 19:27
2

To make that work, you need files to be an array, not a variable. Try:

files=("${@:2}")
for f in "${files[@]}"; do
  echo "$f"
done

Example:

$ bash script.sh first "test image.jpg" "another test.txt"
test image.jpg
another test.txt

Discussion

From the original code, consider this statement:

files="${@:2}"

This assigns all arguments after the first to files as a single undifferentiated string. We can see that with this script:

$ cat test.sh
files="${@:2}"
declare -p files
$ bash test.sh first "test image.jpg" "another test.txt"
declare -- files="test image.jpg another test.txt"

As you can see, all distinction between the second and third arguments has been lost.

  • This works! The key is to use () around the elements in assignment and use $var[@] in the for-in loop... Thanks! Will accept this when allowed. – texasbruce Oct 11 '15 at 19:24
  • Glad it worked. To be precise, it needs to be "${var[@]}". Both the double-quotes and the braces are important. – John1024 Oct 11 '15 at 19:30

Not the answer you're looking for? Browse other questions tagged or ask your own question.