Rename JPEGs by adding a prefix according to date taken

1

1

I have a folder with pictures taken with different cameras and all these pictures have a correct DateTimeOriginal EXIF tag set.

Suppose a list of files like this:

20150831_153712.jpg
IMG_5246.JPG
IMG_5247.JPG
20150902_201425.jpg

Now I would like to know how to rename those files in this way, based on the DateTimeOriginal tag of course:

001_IMG_5246.JPG
002_20150831_153712.jpg
003_IMG_5247.JPG
004_20150902_201425.jpg

Basically I want exiftool (or a Windows batch program if that's not possible directly) to sort the whole folder of JPEGs by DateTimeOriginal ascending and the renaming operation should put a counter prefix in front of the filename (thus retaining the original filename).

I would also like how to do a test command to preview the renaming before it occurs (to see if something is wrong, I suppose using the TestName tag).

virtualdj

Posted 2015-09-12T10:44:42.983

Reputation: 106

Answers

1

The items you want to use with ExifTool is the -FileOrder options and the FileSequence tag, plus a little bit of Perl using the Advanced formatting option. The FileOrder option will sort the files based upon the time you list with the option. This slows down ExifTool a bit, because it has to read each file twice, but is still usually faster than other options, such as looping and calling ExifTool for each loop. The FileSequence tag is internal to ExifTool and keeps track of the number of the file currently being processed. It starts at 0, so we'll have to add 1 to it in the advanced processing. That's also were we'll pad out the zeros so it'll be at least 3 characters.

Try this command:
ExifTool "-TestName<${FileSequence;$_=0 x(3-length($_+1)).($_+1)}_$filename" -FileOrder DateTimeOriginal DIR

If it works, just replace -TestName with -FileName:
ExifTool "-FileName<${FileSequence;$_=0 x(3-length($_+1)).($_+1)}_$filename" -FileOrder DateTimeOriginal DIR

To change the number of padded zeros, change the 3 in 3-length to the number you want. To change the starting number, change the 1 in $_+1.

StarGeek

Posted 2015-09-12T10:44:42.983

Reputation: 782

It's almost perfect, thanks! But there are two quircks with 10 and 100 which have a leading 0 too much: '20150831_124835.jpg' --> '009_20150831_124835.jpg', '20150831_131539.jpg' --> '0010_20150831_131539.jpg', 'IMG_5291.JPG' --> '099_IMG_5291.JPG', 'IMG_5292.JPG' --> '0100_IMG_5292.JPG', '20150901_170708.jpg' --> '101_20150901_170708.jpg'. – virtualdj – 2015-09-12T18:50:16.050

It's also worth noting that TestName tag has been introduced since version 9.64 of ExifTool (I was using an older version and it failed with a lot of warning: no writable tags set from **** messages). This may be useful to other users reading this answer. – virtualdj – 2015-09-12T18:53:36.313

Ah, yes. That's because I measured the length of the number, and then added 1 to the number. My stupid mistake attempting to keep the advanced formatting as short as possible. Corrected the command. If you need to start at a different number, you need to correct both occurances of ($_+1). – StarGeek – 2015-09-12T20:47:44.883

1

I checked a couple of rename tools. The main problem is, tools like Rename Master and ExifTool can access EXIF data. But I couldn't find a way to generate a numbered list.

So I wrote a PowerShell script to do it. I commented each line. It should be easy to understand. Just read them.

First thing I had to do, was searching the ID of "DateTimeOriginal" so we can use GetPropertyItem(MyExifID). Second, we add all images from a given folder which actually have a DateTimeOriginal to an array. From here it was easy. We sort the array by date column, increment a simple counter and build our new filename with the pattern 000_oldname.

This script won't modify anything. It only outputs something like:

enter image description here

Use it to check what the script would do. After you've checked the possible results, remove the comment indicator # before the line #Rename-Item $_[0].Fullname $newName. From now on, the script will rename your files accordingly.

RenameFromExif.ps1

# Set image folder to process
$strDirectory = "T:\Pictures"

# Create empty array
$arrSortMe = @()

# Load Windows library to access EXIF data
[void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")

# Loop through all JPGs and JPEGs in the given image folder
Get-ChildItem -Path "$strDirectory\*" -Include *.jpg,*.jpeg | ForEach {

  # Load current image into Powershell as bitmap object
  $img = New-Object -TypeName system.drawing.bitmap -ArgumentList $_.FullName

  # Error handling for images which doesn't have the specified EXIF data
  Try {

    # Get EXIF data with ID 36867 - which is "DateTimeOriginal"
    $intExif = [Byte[]]$img.GetPropertyItem(36867).Value

    # Release image or else later we can't rename it
    $img.Dispose()

    # Convert EXIF data from byte array to string
    $strExif = [System.Text.Encoding]::Default.GetString($intExif, 0, $intExif.Length-1)

    # Convert EXIF data from string to datetime
    $dateExif = [DateTime]::ParseExact($strExif, 'yyyy:MM:dd HH:mm:ss', $null)

    # Add to multidimensional array: [0]=current_file  and [1]=datetime
    $arrSortMe += ,@($_, $dateExif)
  }
  Catch {}
}

Write-host "DateTimeTaken" `t`t`t "New Name" `t`t`t "Old Fullname"
# Sort array by datetime and pipe the sorted array to a foreach loop
$arrSortMe | Sort-Object @{Expression={$_[1]} } | ForEach {$i=0}{

    # Increment a simple counter starting with 0, so the first image gets the "1"
    $i++

    # Format the counter to 3-digits, append an underscore followed by the old image name
    $newName =  $i.ToString("000") + "_" + $_[0].Name    

    # Don't rename images which already have three digits as filename start
    If ($_.Name -notmatch "^[\d]{3}_") {
        #Rename-Item $_[0].Fullname $newName
    }

    # Only for debugging    
    Write-host $_[1].Date `t $newName `t $_[0].Fullname
}

# Clear all variables. System variables are readonly so we don't mind using * to get all
Remove-Variable * -ErrorAction SilentlyContinue

Used ressources

nixda

Posted 2015-09-12T10:44:42.983

Reputation: 23 233

Interesting script, thanks! It works perfectly. But @StarGeek solution seems easier because it only relies on ExifTool. Your commented example is good to learn Powershell, though. – virtualdj – 2015-09-12T18:38:06.080