a slightly detailed renaming query

Started by fteman, December 18, 2011, 05:09:04 PM

Previous topic - Next topic

fteman

I have a small collection of digital cameras which get used across the family and to help with filing them I want to be able to dump all the photos into a single directory and then use exiftool to rename these (based on camera model_date and time taken) and place them into specific directories (based on the camera model). I have been using shuttercount on some cameras but will likely standardise on the date and time.

One issue I have is, in some cases, I want to modify the ${model} output to something slightly more useful, i.e I have an Olympus mju770sw for which ${model} = u770SW,S770SW (see below for the command I use to rename these files).

So far I have been running multiple exiftool commands to do what I want, e.g. exiftool '-r' '-directory=/Users/kbt_minimac/Desktop/picturestosort/OLYMPUS MU770SW_JPG/' '-d' %Y_%m_%d_%H_%M_%S '-filename<OLYMPUS MJU770SW_${datetimeoriginal}%-c.%e' '/Users/kbt_minimac/Desktop/picturestosort1/' . I then use other similar commands for the other cameras.

However, I would like to run a single file (possibly a batch file) to make my life a bit easier.

When I try the following command it works fine for the Nikon models but also creates directories for the non-Nikon cameras.
exiftool '-Directory</Users/Macbook/Desktop/picture test/Pictures2/${model}_%e'  -if '$model = ~ /Nikon/' '-filename<${model}_00${shuttercount}%-c.%e' '/Users/Macbook/Desktop/picture test/Pictures1' '-r' 

So,

1. can I stop the above creating all the other directories? Is my '-if' incorrect?
2. can I use a single command that will work on every file and vary the output directory based on ${model} - by using user-defined tags? I have tried to find suitable documentation but not found anything that makes sense to me! I am happy to be pointed to the appropriate documentation and have another try to work it out.

Not sure if this is easy or difficult but hopefully someone can provide guidance.

thanks


Phil Harvey

First, the problem with the -if expression is that there can't be a space inside the '=~' operator.

About the UserDefined tag, see this thread for an example.

The ValueConv expression may be any valid Perl expression as a string, even something iike this:

    ValueConv => q{
        if ($val =~ /u770SW/i) {
            return 'OLYMPUS MU770SW';
        } elsif ($val =~ /something else/i) {
            return 'SOME OTHER CAMERA';
        } else {
            return $val;
        }
    },


- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

fteman

Thanks very much.

My 'if' was also not working because I hadn't worked out it is case-sensitive (which, if I have interpreted correctly, the /i overrules).

I got the userdefined tag script working once I had figured out that the last comma in your example script wasn't needed!

A couple of other queries...

Out of interest, what does the q do at the start of ValueConv => q{ ?

Lastly, because I have a Nikon D70 and a Nikon D700, I have put D700 before D70 in the script which seems to works correctly, i.e D700 is named as such and D70 is named as such. But can I make the $val =~ command more robust in these cases, i.e. so only if it finds D70 (generally this should be as part of NIKON D70) will it rename files with NIKON D70? I was trying to avoid being so specific as $val = 'NIKON D70' but that might be the simplest solution.




Phil Harvey

Quote from: fteman on December 20, 2011, 08:51:09 AM
My 'if' was also not working because I hadn't worked out it is case-sensitive (which, if I have interpreted correctly, the /i overrules).

Correct.

QuoteI got the userdefined tag script working once I had figured out that the last comma in your example script wasn't needed!

Not needed, but certainly not a problem.  In Perl, an extra comma after the last item in a list or hash isn't a problem.  So there must have been something else going on here.

QuoteOut of interest, what does the q do at the start of ValueConv => q{ ?

There are lots of ways to quote a string in Perl.  Basically, q{...} is like '...' in Perl.

QuoteLastly, because I have a Nikon D70 and a Nikon D700, I have put D700 before D70 in the script which seems to works correctly, i.e D700 is named as such and D70 is named as such. But can I make the $val =~ command more robust in these cases,

Yes, a "\b" matches only at the end of a word.  ie) $val =~ /NIKON D70\b/i will not match "NIKON D700".  Google for "Perl regular expressions" if you want to learn more about this.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

fteman

QuoteNot needed, but certainly not a problem.  In Perl, an extra comma after the last item in a list or hash isn't a problem.  So there must have been something else going on here.

Not being familiar with Perl, I had sort of assumed that the }, closed a { so I had used it more than once. Of course, this wasn't the case earlier in your example script. It took me a while to work this out!

QuoteThere are lots of ways to quote a string in Perl.  Basically, q{...} is like '...' in Perl.

Yes, a "\b" matches only at the end of a word.  ie) $val =~ /NIKON D70\b/i will not match "NIKON D700".  Google for "Perl regular expressions" if you want to learn more about this.

Thanks I will try the \b and take a look at the links and Google search.

I am about to run my script on a (backup) of my library, I am sure this will throw up some minor issues to resolve so I might be back for further advice.

Thanks again for your advice and for Exiftool.

Kevin

fteman


OK things are working well but I get a few warnings/errors. I have run the following command to get a list of all files with warnings (I have also done the same with error instead of warning).

exiftool -if '$warning' -r -T -filename -directory -warning DIR > outputfile.txt

As I have multiple copies of my library I want to know if I have a 'good' copy in another library. I could search through the outputfile(s) to see if the warning shows up across all libraries but it would be easier to check if I had the warning/error in the filename?

I have tried to set the warning as a user defined tag but it doesn't work.

      MyWarning =>
         {
         Desire => 'Warning',
         ValueConv => q
            {
            if ($warning)
               {
               return '$warning';
               }
            else
               {
               return 'No Warning';
               }
            }
         },


I have tried just to reference warning in the filename output '-filename<${MyModel} ${datetimeoriginal} ${MyUniqueID} ${warning} %-c.%e' but also without success.

I am not sure if I am missing something obvious or trying to do something not possible. This is the full command I run:

exiftool -config '/Volumes/FreeAgent GoFlex Drive/Photos_Program_Files/renameallconfig'   '-directory</Path/Photos_Main_Library/${MyDirectory}/${MyModel} %e' '-filename<${MyModel} ${datetimeoriginal} ${MyUniqueID} ${warning} %-c.%e' '-d' %Y' '%m' '%d' '%H' '%M' '%S '/Path/Photos_To_Rename_And_File' '-r'

Thanks, Kevin

Phil Harvey

Hi Kevin,

Interesting.  There were 2 problems in your MyWarning definition:

1) Use $val instead of $warning
2) Don't quote the returned $val

Here is the fixed version:

      MyWarning =>
         {
         Desire => 'Warning',
         ValueConv => q
            {
            if ($val)
               {
               return $val;
               }
            else
               {
               return 'No Warning';
               }
            }
         },


- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

fteman

Thanks

However, this isn't doing what I was expecting it to do. For a file with no warnings I was expecting MyWarning to be set as 'No Warning' but I get an Terminal output saying 'Warning: [minor] Tag "MyWarning" tag not defined' and nothing is appended to the filename. Also, when I get 'Warning: [minor] "datetimeoriginal" not defined' this is not appended to the filename.

I have set the MyWarning as a composite tag and used ${MyWarning} in the -filename text.

I only seem to generate minor warnings, is this an issue?

Kevin

Phil Harvey

Right.  I didn't think this through.  At least one of the Desire'd/Require'd tags must exist.  Try this:

      MyWarning =>
         {
         Desire => {
             0 => 'Warning',
             1 => 'FileName',
         },
         ValueConv => q
            {
            if ($val)
               {
               return $val;
               }
            else
               {
               return 'No Warning';
               }
            }
         },


The minor warnings may be ignored with the -m option.  Usually errors in the maker notes are considered minor.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

fteman

Thanks - that also explained an issue I was seeing with another of my user defined tags. I have made an edit to my code to ensure that they always succeed.

A query: does Require require all inputs to have values and Desire require at least one input to have a value?

Kevin

Phil Harvey

Hi Kevin,

Correct.  Here is the full description from lib/Image/ExifTool/README:

  Require   : [Composite tags only] A hash reference specifying the tags
                  required to calculate the Composite tag value.  The hash
                  values are the names of the required tags, and the keys
                  specify the indices where the tag values are stored in the
                  @val list used in the ValueConv and/or PrintConv expression.
                  The Composite value is only calculated if the values for all
                  Require'd tags are defined.  Require, Desire and Inhibit tag
                  names may be prefixed by an optional group family 0 or 1 name
                  followed by a colon.  Case IS significant.  The keys used by
                  the Require, Desire and Inhibit hashes must not overlap (since
                  they are used as indices into the common @val, @prt and @raw
                  lists), and together the keys must be sequential starting from
                  0.  A special feature allows a scalar tag name to be used
                  instead of the hash reference when only the 0th tag is
                  defined.  For example, the following two definitions are
                  equivalent:

                        Require => { 0 => 'XMP:Title' },
                        Require => 'XMP:Title',

  Desire     : [Composite tags only] This is the same as Require except that
                  the Composite value is calculated even if the specified tags
                  don't exist.  Beware that the elements of @val, @prt and @raw
                  may be undefined for Desire'd tags.  Even if no tags are
                  Require'd, at least one of the Desire'd tags must exist for
                  the Composite tag to be generated.

  Inhibit    : [Composite tags only] Similar to the Require and Desire
                  hashes, except that the Composite tag is NOT built if any of
                  the Inhibit tags exist.


- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).