What I don't like in this renaming method is the colons used in EXIF date and time stamps (e.g. "2013:09:03 20:55:09_IMG_0108.JPG") which might create problems when transferring these files later to other environments (e.g. Windows).
You could run the naming scheme through sed
, to replace the colons with dashes and spaces with underscores, like so:
mv -i "$i" "$(exiftool -CreateDate "$i" | awk -F ': ' '{print $2}' | sed -e 's/:/-/g' -e 's/ /_/g')_$i"
As for making the whole thing lowercase, you could use rename
:
rename 's/(.*)/\L$1/' file.JPG
## or
rename 's/(.*)/\L$1/' *.*
Or you could do it within your script using sed
, as in:
j=$(echo "$i" | sed -e 's/\(.*\)/\L\1/')
...and then use the $j
variable in place of the final $i
of your mv
line. This sed way is slightly more portable (if that matters to you) as different linux distros have different rename commands, while sed is universal.
Or, alternatively, the script can be modified as follows to perform filename conversion to lowercase at the beginning using tr
instead:
for arg
do
tmp="$(echo "$arg" | tr '[A-Z]' '[a-z]')"
mv -i "$arg" "$(exiftool -CreateDate "$arg" | awk -F ': ' '{print $2}' | sed -e 's/:/-/g' -e 's/ /_/g')_$tmp"
done
To perform slightly different commands for different file types, a bash case statement can be used in this script. For example:
#! /usr/bin/env bash
for filename in ./*
do
tmp="$(echo "$filename" | tr '[A-Z]' '[a-z]')"
case "$filename" in
*.MOV|*.mov)
mv -i "$filename" "$(exiftool -a -s -CreateDate-tur "$filename" | awk -F ': ' '{print $2}' | sed -e 's/\-[0-9][0-9]\:00//g' -e 's/\+[0-9][0-9]\:00//g' -e 's/:/-/g' -e 's/ /_/g')_$tmp"
;;
*.JPG|*.jpg)
mv -i "$filename" "$(exiftool -a -s -CreateDate "$filename" | awk -F ': ' '{print $2}' | sed -e 's/:/-/g' -e 's/ /_/g')_"$tmp""
;;
*)
echo 'Not a *.jpg or a *.mov!'
;;
esac
done
In this example, renaming of MOV files that have CreateDate timestamps ANY NUMBER of hours AFTER OR BEFORE JPG files is adjusted by using another (-tur) EXIF data and removing that that time difference suffix, and it might be necessary to change -tur part according to the location set in the system.
This should work for you:
sed 's/"//g' files.csv | while IFS=, read orig new; do mv "$orig" "$new"; done
Explanation:
sed 's/"//g' files.csv
: remove the quotes
IFS=,
: split the input on ,
while read orig new; do ... done
: This will read each input line, split it on the value of $IFS
(here a comma) and save the 1st field as $orig
and the rest as $new
.
mv "$orig" "$new"
: this will rename the files as requested.
If your file only contains file names (like orig.jpg
) and no paths (not /home/take2/orig.jpg
or similar), the command above will only affect files in your current directory. So, you need to open a terminal, cd
to the target directory and run it there.
Test first:
To test this, you can do a dry run first by printing the commands that will be run without actually executing them:
sed 's/"//g' files.csv | while IFS=, read orig new; do echo mv "$orig" "$new"; done
Best Answer
Shell globs should work even with spaces in the names if used properly e.g.
or
[NOTE: these are 'no ops' until the
n
switch or theecho
are removed - so you can check the correct replacement before committing]If you do want to automatically distinguish between jpg and avi files that would also be possible using a more complex loop and the
file
ormimetype
command