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 [2021/06/01 17:42] 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 | ||
| } | } | ||
| - | </sxh> | + | |
| - | Effacer les dossiers vides | + | function Get-Date-Property-Value { |
| - | <sxh powershell> | + | [CmdletBinding()] |
| - | # Set to true to test the script | + | |
| - | $whatIf = $false | + | Param ( |
| - | # Remove hidden files, like thumbs.db | + | $dir, |
| - | $removeHiddenFiles = $false | + | $file, |
| - | # Get hidden files or not. Depending on removeHiddenFiles setting | + | $index |
| - | $getHiddelFiles = !$removeHiddenFiles | + | ) |
| - | # Remove empty directories locally | + | |
| - | Function Delete-EmptyFolder($path) | + | $value = ($dir.GetDetailsof($file, $index) -replace "`u{200e}") -replace "`u{200f}" |
| - | { | + | if ($value -and $value -ne '') { |
| - | # Go through each subfolder, | + | return [DateTime]::ParseExact($value, "g", $null) |
| - | Foreach ($subFolder in Get-ChildItem -Force -Literal $path -Directory) | + | |
| - | { | + | |
| - | # Call the function recursively | + | |
| - | Delete-EmptyFolder -path $subFolder.FullName | + | |
| } | } | ||
| - | # Get all child items | + | return $null |
| - | $subItems = Get-ChildItem -Force:$getHiddelFiles -LiteralPath $path | + | } |
| - | # If there are no items, then we can delete the folder | + | |
| - | # Exluce folder: If (($subItems -eq $null) -and (-Not($path.contains("DfsrPrivate")))) | + | Get-ChildItem -Attributes !Directory $source -Recurse | |
| - | If ($subItems -eq $null) | + | Foreach-Object { |
| - | { | + | Write-Host "Processing $_" |
| - | Write-Host "Removing empty folder '${path}'" | + | |
| - | Remove-Item -Force -Recurse:$removeHiddenFiles -LiteralPath $Path -WhatIf:$whatIf | + | $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 | ||
| } | } | ||
| } | } | ||
| - | # Run the script | ||
| - | Delete-EmptyFolder -path "E:\_Backup" | ||
| </sxh> | </sxh> | ||
| - | Lire des informations dans un fichier image | + | ==== Lire des informations EXIF dans un fichier image ==== |
| <sxh powershell> | <sxh powershell> | ||
| Function Get-Image | Function Get-Image | ||
| Line 64: | Line 121: | ||
| } | } | ||
| - | Get-ChildItem -Path "F:\Deploy\Scripts\Misc\SG - SetWallpaper\Source\Wallpaper" -Filter *.jpg | ForEach-Object { | + | Get-ChildItem -Path "F:\Wallpaper" -Filter *.jpg | ForEach-Object { |
| $image = $_ | Get-Image | $image = $_ | Get-Image | ||
| New-Object PSObject -Property @{ | New-Object PSObject -Property @{ | ||
| Line 74: | Line 131: | ||
| } | } | ||
| </sxh> | </sxh> | ||
| + | ===== Effacer les dossiers vides ===== | ||
| + | <sxh powershell> | ||
| + | # Set to true to test the script | ||
| + | $whatIf = $false | ||
| + | # Remove hidden files, like thumbs.db | ||
| + | $removeHiddenFiles = $false | ||
| + | # Get hidden files or not. Depending on removeHiddenFiles setting | ||
| + | $getHiddelFiles = !$removeHiddenFiles | ||
| + | # Remove empty directories locally | ||
| + | Function Delete-EmptyFolder($path) | ||
| + | { | ||
| + | # Go through each subfolder, | ||
| + | Foreach ($subFolder in Get-ChildItem -Force -Literal $path -Directory) | ||
| + | { | ||
| + | # Call the function recursively | ||
| + | Delete-EmptyFolder -path $subFolder.FullName | ||
| + | } | ||
| + | # Get all child items | ||
| + | $subItems = Get-ChildItem -Force:$getHiddelFiles -LiteralPath $path | ||
| + | # If there are no items, then we can delete the folder | ||
| + | # Exluce folder: If (($subItems -eq $null) -and (-Not($path.contains("DfsrPrivate")))) | ||
| + | If ($subItems -eq $null) | ||
| + | { | ||
| + | Write-Host "Removing empty folder '${path}'" | ||
| + | Remove-Item -Force -Recurse:$removeHiddenFiles -LiteralPath $Path -WhatIf:$whatIf | ||
| + | } | ||
| + | } | ||
| + | # Run the script | ||
| + | Delete-EmptyFolder -path "E:\_Backup" | ||
| + | </sxh> | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ===== 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> | ||