Copy Number is incremented even when a file is copied over itself

Started by Elgyn, September 08, 2018, 08:50:25 AM

Previous topic - Next topic

Elgyn

I've just discovered exiftool I've been really impressed with the amount of flexibility and customisation options - along with the fantastic documentation and forum options. I'm looking forward to do an in-place reorganisation of my photo library.

What's blocking me is that I've hit an issue where the copy number is incremented when the file is already in the correct location.

I've got a test folder that contains two copies of the same file (taken on 2011-09-09):

  • DSCN0025.JPG
  • 2011-09-09\DSCN0025.JPG

Performing a test rename gets the following output (depending on ordering, you can be left without an original DSCN0025.JPG file):
E:\Elgyn\Pictures\Test>exiftool -v -r -d "%Y-%m-%d/%%f%%-3c.%%e" "-testname<filemodifydate" "-testname<createdate" "-testname<datetimeoriginal" .
======== ./2011-09-09/DSCN0025.JPG
Setting new values from ./2011-09-09/DSCN0025.JPG
'./2011-09-09/DSCN0025.JPG' --> '2011-09-09/DSCN0025-001.JPG'
======== ./DSCN0025.JPG
Setting new values from ./DSCN0025.JPG
'./DSCN0025.JPG' --> '2011-09-09/DSCN0025-002.JPG'
    2 directories scanned
    0 image files updated
    2 image files unchanged

(Edit: I changed this to the verbose output, to match the other examples)

The actual move behaves slightly differently, since the original file gets been moved:
E:\Elgyn\Pictures\Test>exiftool -v -r -d "%Y-%m-%d/%%f%%-3c.%%e" "-filename<filemodifydate" "-filename<createdate" "-filename<datetimeoriginal" .
======== ./2011-09-09/DSCN0025.JPG
Setting new values from ./2011-09-09/DSCN0025.JPG
'./2011-09-09/DSCN0025.JPG' --> '2011-09-09/DSCN0025-001.JPG'
======== ./DSCN0025.JPG
Setting new values from ./DSCN0025.JPG
'./DSCN0025.JPG' --> '2011-09-09/DSCN0025.JPG'
    2 directories scanned
    2 image files updated


This is OK, however it gets worse if I run the command again:
E:\Elgyn\Pictures\Test>exiftool -v -r -d "%Y-%m-%d/%%f%%-3c.%%e" "-filename<filemodifydate" "-filename<createdate" "-filename<datetimeoriginal" .
======== ./2011-09-09/DSCN0025-001.JPG
Setting new values from ./2011-09-09/DSCN0025-001.JPG
'./2011-09-09/DSCN0025-001.JPG' --> '2011-09-09/DSCN0025-001-001.JPG'
======== ./2011-09-09/DSCN0025.JPG
Setting new values from ./2011-09-09/DSCN0025.JPG
'./2011-09-09/DSCN0025.JPG' --> '2011-09-09/DSCN0025-001.JPG'
    2 directories scanned
    2 image files updated


My expectation when I perform renaming is that 2011-09-09\DSCN0025.JPG will remain unchanged (since it's a NOP to rename a file to the same name) while the other file will be renamed to 2011-09-09\DSCN0025-001.JPG. I would understand the need to increment the copy number when a file is being copied, since the original will remain. Because this is a move there is no need to preserve the original and therefore no need to increment the copy number.

Is there a way around this? I feel like an -if statement would be particularly complex, given the three potential date sources for renaming (taken from https://www.exiftool.org/filename.html#ex12)

Elgyn

I'm using ExifTool Version 11.10 for Windows.

Based on the changes, a similar issue was fixed in Version 7.10:
Quote- Fixed problem where %c (copy number) was changed when the new file name
    should have been the same as the source file

Elgyn

Interestingly, it works when I'm one directory removed:
E:\Elgyn\Pictures\Test>exiftool -v -r -d "Test/%Y-%m-%d/%%f%%-3c.%%e" "-filename<filemodifydate" "-filename<createdate" "-filename<datetimeoriginal" Test
======== Test/2011-09-09/DSCN0025.JPG
Setting new values from Test/2011-09-09/DSCN0025.JPG
======== Test/DSCN0025.JPG
Setting new values from Test/DSCN0025.JPG
'Test/DSCN0025.JPG' --> 'Test/2011-09-09/DSCN0025-001.JPG'
    2 directories scanned
    1 image files updated
    1 image files unchanged


This hints at the actual problem: ExifTool doesn't see './2011-09-09/DSCN0025.JPG' as the same file as '2011-09-09/DSCN0025.JPG'. I still see this as an issue, but at least there's a workaround below.

Slightly modifying my script gives me the correct behaviour:
E:\Elgyn\Pictures\Test\Test>exiftool -v -r -d "./%Y-%m-%d/%%f%%-3c.%%e" "-filename<filemodifydate" "-filename<createdate" "-filename<datetimeoriginal" .
======== ./2011-09-09/DSCN0025.JPG
Setting new values from ./2011-09-09/DSCN0025.JPG
======== ./DSCN0025.JPG
Setting new values from ./DSCN0025.JPG
'./DSCN0025.JPG' --> './2011-09-09/DSCN0025-001.JPG'
    2 directories scanned
    1 image files updated
    1 image files unchanged


Test test rename still fails to see it as the same, however it's not as much of an issue:
E:\Elgyn\Pictures\Test\Test>exiftool -v -r -d "./%Y-%m-%d/%%f%%-3c.%%e" "-testname<filemodifydate" "-testname<createdate" "-testname<datetimeoriginal" .
======== ./2011-09-09/DSCN0025.JPG
Setting new values from ./2011-09-09/DSCN0025.JPG
'./2011-09-09/DSCN0025.JPG' --> './2011-09-09/DSCN0025-001.JPG'
======== ./DSCN0025.JPG
Setting new values from ./DSCN0025.JPG
'./DSCN0025.JPG' --> './2011-09-09/DSCN0025-002.JPG'
    2 directories scanned
    0 image files updated
    2 image files unchanged

StarGeek

Just letting you know your post isn't being ignored.  It's something I don't have an answer to and Phil is afk for a few days.
"It didn't work" isn't helpful. What was the exact command used and the output.
Read FAQ #3 and use that cmd
Please use the Code button for exiftool output

Please include your OS/Exiftool version/filetype

Elgyn

Not a problem, thanks for the update StarGeek.

I had a look at the source and it looks like it's only doing an equality check for filenames ($filename eq $okfile) in NextUnusedFilename, rather than using some sort of equivalence function:
return $filename if defined $okfile and $filename eq $okfile;
There is a similar check for filenames through the code, for example when checking whether to output the File name is unchanged warning, below.

I made a small modification to DoHardLink, which got me the behaviour I was hoping for when doing test renames:
sub DoHardLink($$$$)
{
    my ($et, $src, $hardLink, $testName) = @_;
...
    if (defined $testName) {
        $testName = NextUnusedFilename($testName, $src, 1);
        if ($usedFileName{$testName}) {
            $et->Warn("File '${testName}' would exist");
        } elsif ($et->SetFileName($src, $testName, 'Test') == 1) {
            $usedFileName{$testName} = 1;
        }
    }


Running the test rename again gives me the expected behaviour:
E:\Elgyn\Pictures\Test> exiftool -v -r -d "./%Y-%m-%d/%%f%%
-3c.%%e" "-testname<filemodifydate" "-testname<createdate" "-testname<datetimeoriginal" .
======== ./2011-09-09/DSCN0025.JPG
Setting new values from ./2011-09-09/DSCN0025.JPG
Warning = File name is unchanged
Warning: File name is unchanged - ./2011-09-09/DSCN0025.JPG
======== ./DSCN0025.JPG
Setting new values from ./DSCN0025.JPG
'./DSCN0025.JPG' --> './2011-09-09/DSCN0025-001.JPG'
    2 directories scanned
    0 image files updated
    2 image files unchanged


Whether this is actually what you want the standard behaviour to be is another question...

Phil Harvey

Thanks for pointing out these inconsistencies and for suggesting a solution to one.  Your solution looks good, but I need to think about this to be sure there aren't any unwanted side-effects.

Regarding the inconsistency due to testing for an exact filename match, I propose this patch:

In NextUnusedFilename(), change

        return $filename if defined $okfile and $filename eq $okfile;

to

        if (defined $okfile) {
            return $filename if $filename eq $okfile;
            my ($fn, $ok) = (AbsPath($filename), AbsPath($okfile));
            return $okfile if defined $fn and defined $ok and $fn eq $ok;
        }


The effect you found where the copy number is added twice to the file is as designed.  If you start with a file that already contains a copy number, then %f contains that number.  To avoid this, you could use %8f to trim the filename to 8 characters to remove any existing copy number before adding another with %-c.

There is a 4th problem where TestName gives a different result for a filename that was moved out of the way.  I'll work on fixing this too.

- Phil

Edit:  There will still remain this problem.  Fixing this may be more trouble than it is worth.  The behaviour is correct if paths are specified consistently in the command:

> exiftool a.jpg -testname=a.jpg
Warning: File name is unchanged - a.jpg
    0 image files updated
    1 image files unchanged
> exiftool a.jpg -testname=./a.jpg
Warning: File './a.jpg' already exists - a.jpg
    0 image files updated
    1 image files unchanged


(this behaviour is the same when setting FileName)
...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 ($).

Elgyn

Wow this is great!

Thanks for your thoughtful response. I didn't know about the %8f trick - I'll have a look at adding it to my scripts.