0

I have a directory of pictures, which can contain jpeg, jpg, and png files. I want to loop through them in a bash script. Its possible for the directory not to contain any png files, or jpeg files, or jpg files. If a file extension doesn't exist, my script gives an error. How to ignore these?

for file in *.{jpg,jpeg,png} ; do
 echo $file
Andreas Louv
  • 46,145
  • 13
  • 104
  • 123
user2611836
  • 386
  • 4
  • 6
  • 17
  • Possible duplicate of [Matching files with various extensions using for loop](https://stackoverflow.com/q/6223817/608639), [for loop for multiple extension and do something with each file](https://stackoverflow.com/q/12259331/608639), [Loop over multiple file extensions from bash script](https://stackoverflow.com/q/49103942/608639), [for loop in bash go though files with two specific extensions](https://stackoverflow.com/q/34382072/608639), etc. – jww Aug 19 '18 at 06:46

3 Answers3

3

You can check if the file exists:

for file in *.{jpg,jpeg,png}; do
  [ -e "$file" ] || continue
  # Here "$file" exists
done

You can also use shopt -s nullglob which will avoid expanding to non existing files:

shopt -s nullglob
for file in *.{jpg,jpeg,png}; do
  # Here "$file" exists
done
Andreas Louv
  • 46,145
  • 13
  • 104
  • 123
2

You can set the nullglob option, which causes a wildcard that has no matches to expand to an empty list instead of expanding to itself.

shopt -s nullglob
for file in *.{jpg,jpeg,png}; do
Barmar
  • 741,623
  • 53
  • 500
  • 612
2

You can also use extended patterns.

shopt -s extglob nullglob
for file in *.@(jpg|jpeg|png); do
    echo "$file"
done

*.{jpg,jpeg,png} expands first to *.jpg *.jpeg *.png; each of the three patterns then undergoes path name expansion. *.@(jpg|jpeg|png), on the other hand, is a single pattern that undergoes path name expansion.

chepner
  • 497,756
  • 71
  • 530
  • 681