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> |