Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

For-loop over glob returns single string instead of list

I’m trying to loop over images in a directory, but instead of one image per loop, my for-loop only iterates once and the loop variable contains all the images.

#!/bin/bash

IMAGEDIR="/home/user/myimages/"

for file in "$IMAGEDIR*.jpg"; do 
  echo $file
  echo "next file"
done

Outputs:

/home/user/myimages/A.jpg /home/user/myimages/B.jpg /home/user/myimages/C.jpg
next file

I would expect it to output:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

/home/user/myimages/A.jpg 
next file
/home/user/myimages/B.jpg 
next file
/home/user/myimages/C.jpg
next file

I’ve looked at several other questions, and I don’t think I should need a nested for loop.

Additionally, I figured out that it works if I use a slightly different format

#!/bin/bash

IMAGEDIR="/home/user/myimages/"

for file in "$IMAGEDIR"*.jpg; do 
  echo $file
  echo "next file"
done

Why does the first glob return a single string and the second one return a list?

>Solution :

Why does the first glob return a single string and the second one return a list?

Because quotation suppresses pathname expansion, but quote removal leaves your glob subject to expansion later.

Consider your first example …

for file in "$IMAGEDIR*.jpg"; do 
  echo $file
  echo "next file"
done

Parameter expansion applies within double quotes, so it expands "$IMAGEDIR*.jpg" to "/home/user/myimages/*.jpg". The quoting suppresses the significance of * for pathname expansion, however, and no other expansions apply, so "/home/user/myimages/*.jpg" is the final expanded version. Which is then subject to quote removal, so the first and only value that file take in that loop is (literally) /home/user/myimages/*.jpg.

In the body of the loop, then, parameter expansion expands echo $file to echo /home/user/myimages/*.jpg. The * is not quoted now, and pathname expansion happens after parameter expansion, so you get one echo command with the names of all the matching files as arguments (supposing that there are any matching files).

The difference in your second example is the placement of the quotation marks. With the * outside the quotation marks in the for line, you get pathname expansion there, resulting in several different values for variable file to take on successive iterations of the loop.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading