I thought this would be simple – but it is proving more complex than I expected.
I want to iterate through all the files of a particular type in a directory, so I write this:
#!/bin/bash
for fname in *.zip ; do
echo current file is ${fname}
done
This works as long as there is at least one matching file in the directory. However if there are no matching files, I get this:
current file is *.zip
I then tried:
#!/bin/bash
FILES=`ls *.zip`
for fname in "${FILES}" ; do
echo current file is ${fname}
done
While the body of the loop does not execute when there are no files, I get an error from ls:
ls: *.zip: No such file or directory
How do I write a loop which cleanly handles no matching files?
Best Answer
In
bash
, you can set thenullglob
option so that a pattern that matches nothing "disappears", rather than treated as a literal string:In POSIX shell script, you just verify that
fname
exists (and at the same time with[ -f ]
, check it is a regular file (or symlink to regular file) and not other types like directory/fifo/device...):Replace
[ -f "$fname" ]
with[ -e "$fname" ] || [ -L "$fname ]
if you want to loop over all the (non-hidden) files whose name ends in.zip
regardless of their type.Replace
*.zip
with.*.zip .zip *.zip
if you also want to consider hidden files whose name ends in.zip
.