How can I move images/videos to Make/Model/Year/Month/Day tree, and rename all file extension to lower case.
And only when file already exist, auto append a counter.
I am using Fedora 27.
Try this:
exiftool '-testname<${make;}/${model;}/${CreateDate}/%f%-c.%le' -d %Y/%m/%d -r DIR
If you are happy with the results, then replace "testname" with "filename" to actually do the renaming.
- Phil
Thank you very much!
What will happen if the media file do not have the $make or $model defined?
When to use $datetimeoriginal vs $CreateDate ?
I used CreateDate because videos tend not to have datetimeoriginal, but you can use multiple arguments with different date/time tags. See here (https://exiftool.org/filename.html) for some examples. The last valid one takes precedence. The -p option documentation explains what happens when a tag is missing:
If a specified tag does not exist, a minor warning is issued and
the line with the missing tag is not printed. However, the -f
option may be used to set the value of missing tags to '-' (but
this may be configured via the MissingTagValue API option), or the
-m option may be used to ignore minor warnings and leave the
missing values empty.
Thank you Phil!
I need to read and test before using this -p option.
Currently, I am using this as the 1st move command of my library:
exiftool -r -d %Y/%Y%m/%Y%m%d '-directory<${make;}/${model;}/$createdate' '-directory<${make;}/${model;}/$datetimeoriginal' DIR
Then I find out some files have GPSDateTime but none of CreateDate nor DateTimeOriginal.
And further, some files do not have Make nor Model.
How can I write a single command to do the follow:
Use GPSDateTime, DateTimeOriginal, CreateDate in order of preference.
Use Make/Model if defined.
To produce a result tree like:
Make/Model/YY/YYmm/YYmmdd
YY/YYmm/YYmmdd
Try this:
exiftool -r -d %Y/%Y%m/%Y%m%d '-directory<$createdate' '-directory<${make;}/${model;}/$createdate' '-directory<${make;}/${model;}/$datetimeoriginal' DIR
I didn't imply that you should use the -p option -- it is just that the advanced formatting feature is explained there.
But I thought you wanted a copy number added to the file name for duplicate files, and a lower-case extension. This is why I set FileName instead of Directory.
- Phil
Hi Phil,
Thank you very much for your replies! I am sorry if I am not clear enough.
I want to do it all:
- change EXT to lower case
- append copy number when filename conflicts at destination folder
- sort images into make/model/date if make/model is defined, otherwise sort into date only
- sort into date if not defined
- trust GPSDateTime > DateTimeOriginal > CreateDate > FileModifyTime
- some images received by Whatsapp have IPTCDigest defined. I want to sort those under WA/date folder.
I am trying to use:
# Pass 1 - sort into make/mode/date or date tree
exiftool -d %Y/%Y%m/%Y%m%d \
'-filename<${createdate}/%f%-c.%le' \
'-filename<${make;}/${model;}/${createdate}/%f%-c.%le' \
'-filename<${make;}/${model;}/${datetimeoriginal}/%f%-c.%le' \
-r DIR
# Pass 2 - sort into Whatsapp/date tree if IPTCDigest defined
exiftool -d %Y/%Y%m/%Y%m%d \
-if '${IPTCDigest}' \
'-filename<Whatsapp/${FileModifyDate}/Whatsapp-%f%-c.%le' \
-r DIR
# Pass 3 - sort remaining files based on FileModifyDate
exiftool -d %Y/%Y%m/%Y%m%d \
'-filename<${FileModifyDate}/%f%-c.%le' \
-r DIR
I would like to know if I can do the above 3 passes in one go.
Thanks in advance!
Try this:
exiftool -d %Y/%Y%m/%Y%m%d \
'-filename<${FileModifyDate}/%f%-c.%le' \
'-filename<Whatsapp/${FileModifyDate}${IPTCDigest;$_=""}/Whatsapp-%f%-c.%le' \
'-filename<${createdate}/%f%-c.%le' \
'-filename<${make;}/${model;}/${createdate}/%f%-c.%le' \
'-filename<${make;}/${model;}/${datetimeoriginal}/%f%-c.%le' \
-r DIR
Basically, you just sort the assignments in the reverse order of priority, and the last valid assignment takes precedence. Here the only trick was making one assignment valid only if IPTCDigest exists, without inserting IPTCDigest into the FileName.
Again, you can test this with TestName before setting all the FileName's.
- Phil
That's is a great trick to learn!
Thank you very much Phil, it works like a charm!
One more question:
When I run the command, I always run exiftool at the Target folder.
Can I specified a Target folder in the command line as option, so that images in the Source folder will still be moved?
You can specify a target directory in each FileName argument (eg. '-filename<SOME_TARGET_DIRECTORY/${FileModifyDate}/%f%-c.%le')
- Phil
Thank you for the reminder, Phil!
I am actually using this without realizing it! Sorry for the dumb questions.
Endless questions:
In the Make / Model strings, the manufacturers are using different Upper/Lower cases. Some with '.' and some without.
How can I manually provide a static mapping, such that all new sortings will always be using a "mapped" folders for the Make/Model tags?
There are examples in this forum of people doing similar things. Here is an old one that still applies (https://exiftool.org/forum/index.php/topic,2480.0.html). Basically, a technique is to create a user-defined Composite tag (https://exiftool.org/config.html) to translate the camera model name into anything you want.
- Phil
Thank you very much Phil!
Now I have a immediate need to learn custom tags.
Hi Phil,
Thank you very much, I have some progress. And more questions.
Following your links, I am trying with the following:
MyModel => {
Require => {
0 => 'Model',
},
ValueConv => '$val[0]',
PrintConv => {
'iPhone 5s' => "iPhone 5S",
#'iPhone 6,2 - 8.0.2' => "iPhone 6",
#'iPhone 6,2 - 8.1.1' => "iPhone 6",
#'iPhone 6,2 - 8.1.2' => "iPhone 6",
#'iPhone 6s' => "iPhone 6S",
#'iPhone 6s Plus' => "iPhone 6S Plus",
},
},
When the original Model is indeed "iPhone 5s", MyModel return "iPhone 5S" correctly. But for original Modes not defined in my table yet, like "iPhone 6s", MyModel returned "Unknown (iPhone 6s)".
How to make MyModel return the original Model if it is not defined in my custom list?
To do this, add the following line as one of the entries in the PrintConv lookup:
OTHER => sub { shift }, # pass all other values straight through
- Phil
That is exactly what I need.
Thank you!
I put my work file here for easy reference:
# Begin of ~/.ExifTool_config
%Image::ExifTool::UserDefined = (
'Image::ExifTool::Composite' => {
MyModel => {
Require => {
0 => 'Model',
},
ValueConv => '$val[0]',
PrintConv => {
'iPhone 5S' => "iPhone 5s",
'iPhone 6,2 - 8.0.2' => "iPhone 6",
'iPhone 6,2 - 8.1.1' => "iPhone 6",
'iPhone 6,2 - 8.1.2' => "iPhone 6",
'iPhone 6S' => "iPhone 6s",
'iPhone 6S Plus' => "iPhone 6s Plus",
OTHER => sub { shift }, # pass all other values straight through
},
},
},
);
1; #end