This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
script:powershell:multimedia:photo [2020/11/08 12:37] admin |
script:powershell:multimedia:photo [2022/10/23 09:35] (current) admin [Organiser ces photos avec la lecture de l'exif] |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== PowerShell et la photo ====== | ====== PowerShell et la photo ====== | ||
- | Déplacer les fichiers par date vers un autre dossier | + | ===== Organiser ces photos avec la lecture de l'exif ===== |
+ | L'EXIF, c'est un format de fichier utilisé pour les images prises par un appareil photographique numérique, la première version de l'Exif date de 1995.\\ **C'est une mine d'or pour organiser ces photos.**\\ Je suis tombé sur le travail de **Jon Gallant**, [[https://blog.jongallant.com/2021/03/organize-photos-powershell/|sur son blog ]], depuis je n'utilise que ce script.\\ Attention pour les utilisateurs de la suite Adobe, on est loin des capacités d'un [[https://helpx.adobe.com/camera-raw/using/navigate-open-save-images-camera.html|Adobe Camera Raw]]. | ||
<sxh powershell> | <sxh powershell> | ||
- | $Destination = 'F:\Photos\' | + | Param( |
- | $Source = 'F:\Photos\2019' | + | [string]$source, |
- | Get-ChildItem -Path $Source -File -Filter *.jpg -Recurse| ForEach-Object { | + | [string]$dest, |
- | $Year = $_.lastwritetime.year.ToString("0000") | + | [string]$format = "yyyy/MM_yyyy/dd_MM_yyyy" |
- | $Month = $_.lastwritetime.month.ToString("00") | + | ) |
- | $Day = $_.lastwritetime.day.ToString("00") | + | |
- | $D = Join-Path $Destination -ChildPath "$Year\$Month-$Year\$Day-$Month-$Year" | + | $shell = New-Object -ComObject Shell.Application |
- | if ((Test-Path $D) -eq $false){New-Item -Path $D -ItemType Directory -Force | Out-Null} | + | |
- | Move-Item -Path $_.FullName -Destination (Join-Path -Path $D -ChildPath $_.name ) -Force | + | function Get-File-Date { |
+ | [CmdletBinding()] | ||
+ | Param ( | ||
+ | $object | ||
+ | ) | ||
+ | |||
+ | $dir = $shell.NameSpace( $object.Directory.FullName ) | ||
+ | $file = $dir.ParseName( $object.Name ) | ||
+ | |||
+ | # First see if we have Date Taken, which is at index 12 | ||
+ | $date = Get-Date-Property-Value $dir $file 12 | ||
+ | |||
+ | if ($null -eq $date) { | ||
+ | # If we don't have Date Taken, then find the oldest date from all date properties | ||
+ | 0..287 | ForEach-Object { | ||
+ | $name = $dir.GetDetailsof($dir.items, $_) | ||
+ | |||
+ | if ( $name -match '(date)|(created)') { | ||
+ | |||
+ | # Only get value if date field because the GetDetailsOf call is expensive | ||
+ | $tmp = Get-Date-Property-Value $dir $file $_ | ||
+ | if ( ($null -ne $tmp) -and (($null -eq $date) -or ($tmp -lt $date))) { | ||
+ | $date = $tmp | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | return $date | ||
+ | } | ||
+ | |||
+ | function Get-Date-Property-Value { | ||
+ | [CmdletBinding()] | ||
+ | |||
+ | Param ( | ||
+ | $dir, | ||
+ | $file, | ||
+ | $index | ||
+ | ) | ||
+ | |||
+ | $value = ($dir.GetDetailsof($file, $index) -replace "`u{200e}") -replace "`u{200f}" | ||
+ | if ($value -and $value -ne '') { | ||
+ | return [DateTime]::ParseExact($value, "g", $null) | ||
+ | } | ||
+ | return $null | ||
+ | } | ||
+ | |||
+ | Get-ChildItem -Attributes !Directory $source -Recurse | | ||
+ | Foreach-Object { | ||
+ | Write-Host "Processing $_" | ||
+ | |||
+ | $date = Get-File-Date $_ | ||
+ | |||
+ | if ($date) { | ||
+ | |||
+ | $destinationFolder = Get-Date -Date $date -Format $format | ||
+ | $destinationPath = Join-Path -Path $dest -ChildPath $destinationFolder | ||
+ | |||
+ | # See if the destination file exists and rename until we get a unique name | ||
+ | $newFullName = Join-Path -Path $destinationPath -ChildPath $_.Name | ||
+ | if ($_.FullName -eq $newFullName) { | ||
+ | Write-Host "Skipping: Source file and destination files are at the same location. $_" | ||
+ | return | ||
+ | } | ||
+ | |||
+ | $newNameIndex = 1 | ||
+ | $newName = $_.Name | ||
+ | |||
+ | while (Test-Path -Path $newFullName) { | ||
+ | $newName = ($_.BaseName + "_$newNameIndex" + $_.Extension) | ||
+ | $newFullName = Join-Path -Path $destinationPath -ChildPath $newName | ||
+ | $newNameIndex += 1 | ||
+ | } | ||
+ | |||
+ | # If we have a new name, then we need to rename in current location before moving it. | ||
+ | if ($newNameIndex -gt 1) { | ||
+ | Rename-Item -Path $_.FullName -NewName $newName | ||
+ | } | ||
+ | |||
+ | Write-Host "Moving $_ to $newFullName" | ||
+ | |||
+ | # Create the destination directory if it doesn't exist | ||
+ | if (!(Test-Path $destinationPath)) { | ||
+ | New-Item -ItemType Directory -Force -Path $destinationPath | ||
+ | } | ||
+ | |||
+ | robocopy $_.DirectoryName $destinationPath $newName /mov | ||
+ | } | ||
} | } | ||
</sxh> | </sxh> | ||
- | Effacer les dossiers vides | + | |
+ | ==== Lire des informations EXIF dans un fichier image ==== | ||
+ | <sxh powershell> | ||
+ | Function Get-Image | ||
+ | { | ||
+ | begin{ | ||
+ | [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") |Out-Null | ||
+ | } | ||
+ | process{ | ||
+ | $fi=[System.IO.FileInfo]$_ | ||
+ | if( $fi.Exists){ | ||
+ | $img = [System.Drawing.Image]::FromFile($_) | ||
+ | $img.Clone() | ||
+ | $img.Dispose() | ||
+ | }else{ | ||
+ | Write-Host "File not found: $_" -fore yellow | ||
+ | } | ||
+ | } | ||
+ | end{} | ||
+ | } | ||
+ | |||
+ | Get-ChildItem -Path "F:\Wallpaper" -Filter *.jpg | ForEach-Object { | ||
+ | $image = $_ | Get-Image | ||
+ | New-Object PSObject -Property @{ | ||
+ | File = $_.name | ||
+ | Fullname = $_.Fullname | ||
+ | Height = $image.Height | ||
+ | Width = $image.Width | ||
+ | }; | ||
+ | } | ||
+ | </sxh> | ||
+ | ===== Effacer les dossiers vides ===== | ||
<sxh powershell> | <sxh powershell> | ||
# Set to true to test the script | # Set to true to test the script | ||
Line 45: | Line 164: | ||
+ | |||
+ | |||
+ | |||
+ | ===== Déplacer les fichiers par date vers un autre dossier ===== | ||
+ | Je n'utilise plus cette version de script, je préfère utiliser le script avec l'utilisation des informations EXIF | ||
+ | <sxh powershell> | ||
+ | $Destination = 'F:\Photos\' | ||
+ | $Source = 'F:\Photos\2019' | ||
+ | Get-ChildItem -Path $Source -File -Filter *.jpg -Recurse| ForEach-Object { | ||
+ | $Year = $_.lastwritetime.year.ToString("0000") | ||
+ | $Month = $_.lastwritetime.month.ToString("00") | ||
+ | $Day = $_.lastwritetime.day.ToString("00") | ||
+ | $D = Join-Path $Destination -ChildPath "$Year\$Month-$Year\$Day-$Month-$Year" | ||
+ | if ((Test-Path $D) -eq $false){New-Item -Path $D -ItemType Directory -Force | Out-Null} | ||
+ | Move-Item -Path $_.FullName -Destination (Join-Path -Path $D -ChildPath $_.name ) -Force | ||
+ | } | ||
+ | </sxh> |