Renaming .jpg files in subdirectories without changing the creation date (on a MAC)

One possibility using the EXIF creation date would be (untested but should work):

  • move all your files into the same directory, renaming them to a unique name (e.g. the name of the containing directory plus the .jpg suffix)

    cd ~/foo
    for i in */; do
      # moves the file (supposedly named orig.jpg) in current directory
      # renaming it to the name of the containing sub directory
      mv ${i}orig.jpg ./`basename $i`.jpg
      # removes the subdirectory, assuming it is now empty
      rmdir $i;
    done
    

    If the files are not always named the same way, but there is only a single file (with name ending in .jpg) in the subdirectory, you can of course replace the mv command with:

      mv ${i}*.jpg ./`basename $i`.jpg
    
  • then rename them using exiftool:

    exiftool -d %Y%m%d_%H%M%S.jpg "-filename<CreateDate" ~/foo
    

    This assumes that no files will have the same creation time down to the seconds level. If there is a risk of filename collision, you can use a variant that adds a suffix to the file name in case of a duplicate name:

    exiftool -d %Y%m%d_%H%M%S%-c.jpg "-filename<CreateDate" ~/foo
    

More info about the renaming function of exiftool here: http://www.sno.phy.queensu.ca/~phil/exiftool/filename.html


Unfortunately, OSX does not have the GNU tools but instead, it's core utilities are forks of the BSD versions. This means that many command line answers that you find for Linux won't apply. Either because the relevant options are missing or because they're different.

I don't have an OSX machine to test this on but based on the OSX man pages for stat and date, this should do what you need:

find . -name orig.jpg | 
    while read file; do
     echo mv "$file" "$(date -jf "$(stat -f '%m' "$file")" +%Y%m%d_%H%M%S)".jpg
    done

If your directory names can contain spaces or other strange characters, use this instead:

find . -name orig.jpg -print0 | 
    while IFS= read -r -d '' file; do
     echo mv "$file" "$(date -jf "$(stat -f '%m' $file)" +%Y%m%d_%H%M%S)".jpg
    done

That will just print the commands that will be run. If they are correct, remove the echo and run it again to actually rename the files. As I said, I can't test this since I don't have access to an OSX machine so you might have to tweak it. Have a look at the man pages I linked to (or run man stat on your machine). I am not sure that OSX's date can deal with the output of stat -f '%m', if not, let me know and I'll try and help.

Explanation

  • find . -name orig.jpg : recursively find all files called origin.jpg in the current folder.
  • while read file; ... ; do : this will save each of the file names found by find as $file and then run the next commands on each of them.
  • stat -f '%m' $file : this should show the modification time of the file in a human-readable format.
  • $(date -jf "DATE" +%Y%m%d_%H%M%S) : print the date given by DATE as YYMMDD_HHMMSS. Since we are giving it the output of stat -f '%m' $file, that will print the date that the file was modified.
  • mv "$file" "$(date -jf "$(stat -f '%m' $file)" +%Y%m%d_%H%M%S)".jpg : rename $file to the date returned by date and .jpg.

The equivalent command on Linux is:

find . -name orig.jpg | 
    while read file; do 
        echo mv "$file" "$(date -d "$(stat -c '%y' $file)" +%Y%m%d_%H%M%S)".jpg
   done