0

I'm writing a script to move files (Dropbox Camera Uploads, for instance) to year named folders, like this:

#!/bin/bash
#
# Separate (camera) images on directory
# to year named folders.
#
# All files must be named as "yyyy-mm-dd HH:MM:SS.ext"
#
for img in *.{jpg,jpeg,png}; do
  year=${img:0:4}
  [ -d "$year" ] || mkdir "$year"
  mv -iv "$img" "$year/"
done

The script works as expected for matchin files, but when there isn't any file with some extension, expands to *.ex (first two extension chars). Then it creates empty directories as follows:

'*.jp'
'*.jp'
'*.pn'

How can I just ignore no matching files?

paulodiovani
  • 1,208
  • 2
  • 16
  • 34

3 Answers3

6

You want the nullglob option; patterns that don't match anything are ignored, rather than treated literally.

shopt -s nullglob
for f in *.does_not_exist; do
    echo "This won't be reached"
done
chepner
  • 497,756
  • 71
  • 530
  • 681
2

You have two primary options. One, as @chepner suggests, is to turn on nullglob, which makes unmatched globs expand to null:

shopt -s nullglob

The other is to test to see if the file is there before doing anything with it:

for img in *.{jpg,jpeg,png}; do
  if [ -f "$img" ]; then   # not true for '*.jpg' etc
    year=${img:0:4}
    [ -d "$year" ] || mkdir "$year"
    mv -iv "$img" "$year/"
  fi
done

You could also use mkdir -p and skip the -d test.

Mark Reed
  • 91,912
  • 16
  • 138
  • 175
1

you can check to see if the file exists first, then continue the loop if not

#!/bin/bash
#
# Separate (camera) images on directory
# to year named folders.
#
# All files must be named as "yyyy-mm-dd HH:MM:SS.ext"
#
for img in *.{jpg,jpeg,png}; do
  [ ! -f "$img" ] && continue
  year=${img:0:4}
  [ -d "$year" ] || mkdir "$year"
  mv -iv "$img" "$year/"
done
Jeff Puckett
  • 37,464
  • 17
  • 118
  • 167