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, 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 Adobe Camera Raw.
Param(
[string]$source,
[string]$dest,
[string]$format = "yyyy/MM_yyyy/dd_MM_yyyy"
)
$shell = New-Object -ComObject Shell.Application
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
}
}
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
};
}
# 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"
Je n'utilise plus cette version de script, je préfère utiliser le script avec l'utilisation des informations EXIF
$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
}