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:
/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?
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.
*
out of the quotation marks, but if there was any point to the quotation marks in the first place (and there was) then you should have quoted $file
inside the loop body. And those issues combined to disguise both. — Aug 06, 2022 at 00:44 External links referenced by this document:
Local articles referenced by this article: