1

I'm trying to iterate through all zip files in a bash script (I'm using Cygwin, but I kind of doubt this is a bug with Cygwin).

It looks like this right now:

for z in *.zip
do
    echo $z
done

which works well when there are zip files in the folder, and it echos exactly the zip files and nothing but the zip files. However, when I do it on a folder that's empty, it echos *.zip, when I'd rather it echo nothing.

What should I be doing? I don't think the right solution is if [ $z != "*.zip ]... but is it?

codeforester
  • 39,467
  • 16
  • 112
  • 140
River Tam
  • 3,096
  • 4
  • 31
  • 51

3 Answers3

3

As one of its steps for executing a command, the shell may perform path expansion in which case it will replace a string, such as *.zip with the list of files that match that glob. If there are no such files, then the string is left unchanged. A reasonable solution is:

for z in *.zip
do
    [ -f "$z" ] && echo $z
done

[ -f "$z" ] verifies that the file exists and is a regular file. The && means that echo will be executed only if that test is passed.

John1024
  • 109,961
  • 14
  • 137
  • 171
3

This is the expected behavior. From the documentation:

If no matching filenames are found, and the shell option nullglob is disabled, the word is left unchanged. If the nullglob option is set, and no matches are found, the word is removed.

So the solution is to set the nullglob option before the loop:

shopt -s nullglob
for z in *.zip
    ...
Barmar
  • 741,623
  • 53
  • 500
  • 612
1

Either that or turning on the nullglob option.

$ set -x
$ echo *.none
+ echo '*.none'
*.none
$ shopt -s nullglob
+ shopt -s nullglob
$ echo *.none
$ echo *.none
+ echo
Etan Reisner
  • 77,877
  • 8
  • 106
  • 148