Powershell script voor het kopiëren van foto's naar datum mappen op basis van EXIF informatie

Een kort Powershell script voor het kopiëren (of verplaatsen) van foto's naar mappen op basis van datum. Hiervoor wordt de EXIF informatie in de foto gebruikt. PowershellDus een foto gemaakt op 22 april 2007 wordt in de map '2007\4\22' geplaatst, dus eerst een map '2007', vervolgens een map '4' en als laatste de map '22'.

fotoopdatum

Om op basis van EXIF informatie te kunnen selecteren is wel een module voor Powershell nodig, deze is hier te vinden: Microsoft Powershell Pack.

 

## Kopieren van (foto)bestanden op basis van EXIF informatie
## Wel het powershellpack nodig voor EXIF informatie, te vinden op http://archive.msdn.microsoft.com/PowerShellPack
## EXIF onderdeel laden met "Import-Module PSImageTools" (zonder quotes in Powershell)
## Controleren met "Get-Module -ListAvailable"
##
## Opmerking: bestanden zonder EXIF informatie komen in de hoofdmap ($basisdoel) te staan
## Cas
## Variabelen, hieronder de paden aanpassen naar behoefte
$bron = "k:\testfotos"
$basisdoel = "k:\testfotos2"
## Begin script
Import-Module PSImageTools
cls
## Bronbestanden
Write-Host "          Bronfolder: " -ForegroundColor DarkGray -NoNewline
Write-Host $bron -ForegroundColor Yellow
 
$bestanden = get-childitem $bron -include * -recurse
 
Write-Host "            Gevonden: " -ForegroundColor DarkGray -NoNewline
Write-Host $bestanden.Count -ForegroundColor Yellow -NoNewline
Write-Host " bestanden" -ForegroundColor DarkGray
foreach ($bestand in $bestanden)
{
  if (!(Test-Path $bestand -PathType Container))
  {
    $datum = ($bestand | Get-Image | Get-ImageProperty).dt
    $dag = $datum.day
    $maand = $datum.month
    $jaar = $datum.year;
    $doel = $basisdoel+"\"+$jaar+"\"+$maand+"\"+$dag
    if (!(Test-Path -path $doel))
    {
       New-Item $doel -type directory
    }
    ## Voor verplaatsen van bestanden ipv kopieren "Copy-Item" veranderen in "Move-Item"
    Write-Host "$bestand -> $doel"
    Copy-Item $bestand $doel 
  }
}

 

 




 

Op verzoek ook een variant gemaakt met een grafische interface (GUI). Het script is in principe heel simpel en controleert helemaal niet op gebruikersfouten, dus let wel op bij het gebruik van dit script!!! De GUI is gemaakt met Primalforms van Sapien.

Het is en blijft een powershell script dus het Microsoft Powershell Pack blijft nodig!

Omdat het een Powershell script is met grafische functies moet powershell gestart worden met de -STA parameter, dus het script op de volgende manier starten (meer info hier):

powershell -STA <folder\naamscript.ps1>

kopieerdatumexifS
 

 

 

 

 

 

 

 

 

 

Nu het script (ook te vinden in downloadsectie):

 

#Generated Form Function
function GenerateForm {
########################################################################
# Code Generated By: SAPIEN Technologies PrimalForms (Community Edition) v1.0.10.0
# Generated On: 12-8-2012 12:23
# Generated By: Cas
########################################################################
#region Import the Assemblies
[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
#endregion
#region Generated Form Objects
$form1 = New-Object System.Windows.Forms.Form
$linkLabel1 = New-Object System.Windows.Forms.LinkLabel
$lblAantalBestanden = New-Object System.Windows.Forms.Label
$lblAantalJPG = New-Object System.Windows.Forms.Label
$txtAantalBestanden = New-Object System.Windows.Forms.TextBox
$txtAantalJPG = New-Object System.Windows.Forms.TextBox
$btnAantalJPG = New-Object System.Windows.Forms.Button
$txtDoel = New-Object System.Windows.Forms.Label
$txtBron = New-Object System.Windows.Forms.Label
$btnStart = New-Object System.Windows.Forms.Button
$btnSelectDoel = New-Object System.Windows.Forms.Button
$btnSelectBron = New-Object System.Windows.Forms.Button
$textBox2 = New-Object System.Windows.Forms.TextBox
$textBox1 = New-Object System.Windows.Forms.TextBox
$openFileDialog1 = New-Object System.Windows.Forms.FolderBrowserDialog
$openFileDialog2 = New-Object System.Windows.Forms.FolderBrowserDialog
$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
#endregion Generated Form Objects
#----------------------------------------------
#Generated Event Script Blocks
#----------------------------------------------
#Provide Custom Code for events specified in PrimalForms.
$btnStart_OnClick= 
{
Import-Module PSImageTools
cls
## Bronbestanden
Write-Host "          Bronfolder: " -ForegroundColor DarkGray -NoNewline
Write-Host $bron -ForegroundColor Yellow
 
$bestanden = get-childitem $bron -include * -recurse
 
Write-Host "            Gevonden: " -ForegroundColor DarkGray -NoNewline
Write-Host $bestanden.Count -ForegroundColor Yellow -NoNewline
Write-Host " bestanden" -ForegroundColor DarkGray
foreach ($bestand in $bestanden)
{
  if (!(Test-Path $bestand -PathType Container))
  {
    $datum = ($bestand | Get-Image | Get-ImageProperty).dt
    $dag = $datum.day
    $maand = $datum.month
    $jaar = $datum.year;
    $doel = $basisdoel+"\"+$jaar+"\"+$maand+"\"+$dag
    if (!(Test-Path -path $doel))
    {
       New-Item $doel -type directory
    }
    ## Voor verplaatsen van bestanden ipv kopieren "Copy-Item" veranderen in "Move-Item"
    Write-Host "$bestand -> $doel"
    Copy-Item $bestand $doel 
  }
}
}
$btnAantalJPG_OnClick= 
{
$AantalJPG = get-childitem $bron -include *.jpg -recurse
$txtAantalJPG.text =  $AantalJPG.Count
$Aantalbestanden = get-childitem $bron -include * -recurse | Where-Object { -not $_.PSIsContainer }
$txtAantalBestanden.text = $Aantalbestanden.Count
}
$btnSelectBron_OnClick= 
{
	$form1.refresh()
    IF ($openFileDialog1.ShowDialog() -eq [Windows.Forms.DialogResult]::OK)
	{
		$textBox1.text = $openFileDialog1.SelectedPath
        $bron = $openFileDialog1.SelectedPath
	}
}
$btnSelectDoel_OnClick= 
{
	IF ($openFileDialog2.ShowDialog() -eq [Windows.Forms.DialogResult]::OK)
	{
		$textBox2.text = $openFileDialog2.SelectedPath
        $basisdoel = $openFileDialog2.SelectedPath
	}
}
$linkLabel1_OnClick=
{
Start-Process "http://archive.msdn.microsoft.com/PowerShellPack"
}
$OnLoadForm_StateCorrection=
{#Correct the initial state of the form to prevent the .Net maximized form issue
	$form1.WindowState = $InitialFormWindowState
}
#----------------------------------------------
#region Generated Form Code
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 198
$System_Drawing_Size.Width = 471
$form1.ClientSize = $System_Drawing_Size
$form1.DataBindings.DefaultDataSourceUpdateMode = 0
$form1.Name = "form1"
$form1.Text = "Kopieer naar datummappen obv EXIF"
$linkLabel1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 13
$System_Drawing_Point.Y = 172
$linkLabel1.Location = $System_Drawing_Point
$linkLabel1.Name = "linkLabel1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 262
$linkLabel1.Size = $System_Drawing_Size
$linkLabel1.TabIndex = 12
$linkLabel1.TabStop = $True
$linkLabel1.Text = "http://archive.msdn.microsoft.com/PowerShellPack"
$linklabel1.add_Click($linklabel1_OnClick)
$form1.Controls.Add($linkLabel1)
$lblAantalBestanden.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 13
$System_Drawing_Point.Y = 142
$lblAantalBestanden.Location = $System_Drawing_Point
$lblAantalBestanden.Name = "lblAantalBestanden"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 100
$lblAantalBestanden.Size = $System_Drawing_Size
$lblAantalBestanden.TabIndex = 11
$lblAantalBestanden.Text = "Aantal bestanden"
$form1.Controls.Add($lblAantalBestanden)
$lblAantalJPG.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 13
$System_Drawing_Point.Y = 108
$lblAantalJPG.Location = $System_Drawing_Point
$lblAantalJPG.Name = "lblAantalJPG"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 72
$lblAantalJPG.Size = $System_Drawing_Size
$lblAantalJPG.TabIndex = 10
$lblAantalJPG.Text = "Aantal JPG''s"
$form1.Controls.Add($lblAantalJPG)
$txtAantalBestanden.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 112
$System_Drawing_Point.Y = 139
$txtAantalBestanden.Location = $System_Drawing_Point
$txtAantalBestanden.Name = "txtAantalBestanden"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 38
$txtAantalBestanden.Size = $System_Drawing_Size
$txtAantalBestanden.TabIndex = 9
$form1.Controls.Add($txtAantalBestanden)
$txtAantalJPG.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 112
$System_Drawing_Point.Y = 105
$txtAantalJPG.Location = $System_Drawing_Point
$txtAantalJPG.Name = "txtAantalJPG"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 38
$txtAantalJPG.Size = $System_Drawing_Size
$txtAantalJPG.TabIndex = 8
$form1.Controls.Add($txtAantalJPG)
$btnAantalJPG.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 165
$System_Drawing_Point.Y = 137
$btnAantalJPG.Location = $System_Drawing_Point
$btnAantalJPG.Name = "btnAantalJPG"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 49
$btnAantalJPG.Size = $System_Drawing_Size
$btnAantalJPG.TabIndex = 7
$btnAantalJPG.Text = "Check Aantal JPG"
$btnAantalJPG.UseVisualStyleBackColor = $True
$btnAantalJPG.add_Click($btnAantalJPG_OnClick)
$form1.Controls.Add($btnAantalJPG)
$txtDoel.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 9
$System_Drawing_Point.Y = 73
$txtDoel.Location = $System_Drawing_Point
$txtDoel.Name = "txtDoel"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 17
$System_Drawing_Size.Width = 33
$txtDoel.Size = $System_Drawing_Size
$txtDoel.TabIndex = 6
$txtDoel.Text = "Doel"
$form1.Controls.Add($txtDoel)
$txtBron.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 9
$System_Drawing_Point.Y = 37
$txtBron.Location = $System_Drawing_Point
$txtBron.Name = "txtBron"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 19
$System_Drawing_Size.Width = 36
$txtBron.Size = $System_Drawing_Size
$txtBron.TabIndex = 5
$txtBron.Text = "Bron"
$form1.Controls.Add($txtBron)
$btnStart.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 364
$System_Drawing_Point.Y = 171
$btnStart.Location = $System_Drawing_Point
$btnStart.Name = "btnStart"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 24
$System_Drawing_Size.Width = 94
$btnStart.Size = $System_Drawing_Size
$btnStart.TabIndex = 4
$btnStart.Text = "Start"
$btnStart.UseVisualStyleBackColor = $True
$btnStart.add_Click($btnStart_OnClick)
$form1.Controls.Add($btnStart)
$btnSelectDoel.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 431
$System_Drawing_Point.Y = 70
$btnSelectDoel.Location = $System_Drawing_Point
$btnSelectDoel.Name = "btnSelectDoel"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 27
$btnSelectDoel.Size = $System_Drawing_Size
$btnSelectDoel.TabIndex = 3
$btnSelectDoel.Text = "..."
$btnSelectDoel.UseVisualStyleBackColor = $True
$btnSelectDoel.add_Click($btnSelectDoel_OnClick)
$form1.Controls.Add($btnSelectDoel)
$btnSelectBron.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 431
$System_Drawing_Point.Y = 34
$btnSelectBron.Location = $System_Drawing_Point
$btnSelectBron.Name = "btnSelectBron"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 27
$btnSelectBron.Size = $System_Drawing_Size
$btnSelectBron.TabIndex = 2
$btnSelectBron.Text = "..."
$btnSelectBron.UseVisualStyleBackColor = $True
$btnSelectBron.add_Click($btnSelectBron_OnClick)
$form1.Controls.Add($btnSelectBron)
$textBox2.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 56
$System_Drawing_Point.Y = 70
$textBox2.Location = $System_Drawing_Point
$textBox2.Name = "textBox2"
$textBox2.ReadOnly = $True
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 369
$textBox2.Size = $System_Drawing_Size
$textBox2.TabIndex = 1
$form1.Controls.Add($textBox2)
$textBox1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 56
$System_Drawing_Point.Y = 34
$textBox1.Location = $System_Drawing_Point
$textBox1.Name = "textBox1"
$textBox1.ReadOnly = $True
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 369
$textBox1.Size = $System_Drawing_Size
$textBox1.TabIndex = 0
$form1.Controls.Add($textBox1)
#endregion Generated Form Code
#Save the initial state of the form
$InitialFormWindowState = $form1.WindowState
#Init the OnLoad event to correct the initial state of the form
$form1.add_Load($OnLoadForm_StateCorrection)
#Show the Form
$form1.ShowDialog()| Out-Null
} #End Function
#Call the Function
if([threading.thread]::CurrentThread.ApartmentState.ToString() -eq 'MTA')               
{               
  write-host -ForegroundColor RED "PowerShell.exe uitvoeren met -STA optie"              
  write-host -ForegroundColor RED "Voorbeeld:"              
  write-host -ForegroundColor RED "    PowerShell -noprofile -STA C:\scripts\GUIUtility.ps1"                
}
GenerateForm