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:
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: http://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: http://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 + "\" + $strDay If (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
#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 + "\" + $strDay
If (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