Organizing my pictures, evolving the script to my taste
I ran the PowerShell script I discussed in my previous blogpost and decided I would change it a bit.
First, I want to be able to sort by month within the year so I have two options:
- change the folder name to following pattern MM-DD-YY
- Add a level to the folder structure so it becomes:
- Year
- Month
- Day
Second, from my 24 GB of pictures on that machine, only 17GB got copied over. The rest didn’t because of exceptions or because I had the same picture in multiple folders. In order not to loose any pictures I changed the script so:
- it writes the error message to a text file
- it copies the .jpg on which the exception was generated to an exceptions folder
So now it gets interesting. Kim has got me developing Powershell code. I never thought I would ever do that since it seems more something an IT Professional would do but there are some advantages to writing this sort of job as a script:
- It is quick and a bit dirty.
- Powershell has non-terminating errors. This reminds me of ‘On Error Resume Next’ and how I kept my VB6 code clean at the time :-)
- I could easily schedule this as a recurring job.
Here’s how I deal with this:
Step 1. I switch to PowerShell 2 because that’s on my Windows 7 machine but more importantly because you then have the Windows PowerShell Integrated Scripting Environment. That’s a tool for running and debugging scripts so exactly what I need.
If you are on Vista you can get it here: https://www.microsoft.com/downloads/details.aspx?FamilyID=c913aeab-d7b4-4bb1-a958-ee6d7fe307bc&displaylang=en
Step 2. I learn about error handling and debugging in PowerShell. This seems like a good place. It’s an old blog series but I’m sure still very relevant: https://blogs.msdn.com/monad/archive/2005/11.aspx
Also install the SDK from the download link in Step 1.
Step 3. Changing the script.
Changing the folder structure is easy. you change it:
from: $DateTaken = $strDay + "-" + $strMonth + "-" + $strYear
$TargetPath = "c:\temp\organized pictures\" + $strYear + "\" + $DateTaken
to: $TargetPath = "c:\temp\organized pictures\" + $strYear + "\" + $strMonth + "\" + $strDay
Fixing the exceptions and adding the exception list is something else. But with the new Try..Catch…Finally structure in PowerShell 2, it is not that difficult at all. I highlighted the interesting sections:
#==============================================================================================
#
# AUTHOR: Kim Oppalfens
# DATE : 12/2/2007, updated by Hans Verbeeck on 10 Jan 2009
#
# COMMENT: Helps you organize your digital photos into a directory structure, based on the Exif data
# found inside the picture. Based on the date picture taken property the pictures will be organized into
# c:\organizedfotos\YYYY\MM\
# ==============================================================================================
[reflection.assembly]::loadfile( "C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll")
$targetFolder = "c:\temp\organized pictures\"
$exceptionFolder = "c:\temp\organized pictures\Exceptions"
#make sure you create this folder yourself as the script won't do that automatically
$Files = Get-ChildItem -recurse -filter *.jpg
foreach ($file in $Files)
{
try
{
$foo=New-Object -TypeName system.drawing.bitmap -ArgumentList $file.fullname
write-host $file.fullname -foregroundcolor Blue
#each character represents an ascii code number 0-10 is date
#10th character is space separator between date and time
#48 = 0 49 = 1 50 = 2 51 = 3 52 = 4 53 = 5 54 = 6 55 = 7 56 = 8 57 = 9 58 = :
#date is in YYYY/MM/DD format
$date = $foo.GetPropertyItem(36867).value[0..9]
$arYear = [Char]$date[0],[Char]$date[1],[Char]$date[2],[Char]$date[3]
$arMonth = [Char]$date[5],[Char]$date[6]
$arDay = [Char]$date[8],[Char]$date[9]
$strYear = [String]::Join("",$arYear)
$strMonth = [String]::Join("",$arMonth)
$strDay = [String]::Join("",$arDay)
$DateTaken = $strDay + "-" + $strMonth + "-" + $strYear
$TargetPath = $targetFolder + $strYear + "\" + $strMonth + "\" + $strDayIf (Test-Path $TargetPath)
{
xcopy /Y/Q $file.FullName $TargetPath
}
Else
{
New-Item $TargetPath -Type Directory
xcopy /Y/Q $file.FullName $TargetPath
}
}
catch
{
$logtext = "`n" + $file.fullname + " FAILED"
Add-Content c:\temp\imagecopyexceptions.txt $logtext
$logtext = $Error[$error.count-1]
Add-Content c:\temp\imagecopyexceptions.txt $logtext
xcopy /Y/Q $file.FullName $exceptionFolder
}
}