ehime
ehime

Reputation: 8375

Unexpected newlines in bash for loop

I am having a newline issue in my BASH code trying to loop the following:

bash-4.3$ vboxmanage list vms
  "node1" {280482b5-3913-4019-aa9a-383f1f3131a1}
  "test_default_1419033096698_75346" {9a2f7b6b-33d8-4997-9c35-9b86f3d183b6}

Knowing that, I get unexpected results below

for name in $(vboxmanage list vms); do
    echo "==> $name"
done

  ## Prints
  ==> "node1"
  ==> {280482b5-3913-4019-aa9a-383f1f3131a1}
  ==> "test_default_1419033096698_75346"
  ==> {9a2f7b6b-33d8-4997-9c35-9b86f3d183b6}

I would expect to get the following though?

  ==> "node1" {280482b5-3913-4019-aa9a-383f1f3131a1}
  ==> "test_default_1419033096698_75346" {9a2f7b6b-33d8-4997-9c35-9b86f3d183b6}

So I attempt to this instead and...

for name in "$(vboxmanage list vms)"; do
    echo "==> $name"
done

  ==> "node1" {280482b5-3913-4019-aa9a-383f1f3131a1}
  "test_default_1419033096698_75346" {9a2f7b6b-33d8-4997-9c35-9b86f3d183b6}

The results are on one line as expected...

What I am curious about is WHY the first example does this, I know well enough that multiple lines should be read with a while loop. I am more curious as to why it is doing this, I am not interested in implementing for as a solution.

Upvotes: 3

Views: 68

Answers (1)

Tom Fenech
Tom Fenech

Reputation: 74625

Your loop is essentially this:

for name in "node1" {280482b5-3913-4019-aa9a-383f1f3131a1} "test_default_1419033096698_75346" {9a2f7b6b-33d8-4997-9c35-9b86f3d183b6}
do
    echo "$name"
done

That is, each of the separate words is being printed in a separate iteration of your loop.

As the FAQ will tell you, use a while read loop instead:

while read -r name
do
    echo "$name"
done < <(vboxmanage list vms)

As the FAQ also mentions, if you want to preserve leading and trailing whitespace, you should use IFS= while read -r name. This clears the value of the Input Field Separator, IFS for the duration of the command.

Upvotes: 6

Related Questions