################################## ###### CONSTANTS ######### ################################## $global:FileTypePropIndex = 11 $global:ImageCreationDatePropIndex = 12 $global:VideoCreationDatePropIndex = 208 ################################## ###### FUNCTIONS ######### ################################## function Get-APImageVideoExtensions { param ( [string] $sourceUrl = "https://cdn.jsdelivr.net/gh/jshttp/mime-db@v1.52.0/db.json" ) $jsonData = (Invoke-RestMethod $sourceUrl).PSObject.Properties $extensions = @() foreach ($item in $jsonData) { if ($item.Name -match "^(image|video)") { $extensions += $item.Value.extensions } } $extensions = $extensions | Sort-Object -Unique return $extensions } function Get-APFileMetaData { param ( [string] $filePath, [int] $propertyIndex ) $folder = (New-Object -ComObject Shell.Application).NameSpace((Split-Path -Parent $filePath)) $folderItem = $folder.ParseName((Split-Path -Leaf $filePath)) $property = $folder.GetDetailsOf( $folderItem, $propertyIndex ) return $property } function Get-APTemporaryDirectory { do { $tempDir = Join-Path -Path $env:TEMP -ChildPath ([System.IO.Path]::GetRandomFileName()) } while (Test-Path $tempDir) return $tempDir } function Get-APDateFromJson { param ( [string] $filePath ) $jsonFilePath = $filePath + ".json" if (-not (Test-Path $jsonFilePath)) { return $null } $jsonContent = Get-Content -Path $jsonFilePath -Raw | ConvertFrom-Json $timestamp = [int64] $jsonContent.photoTakenTime.timestamp return [System.DateTimeOffset]::FromUnixTimeSeconds($timestamp).DateTime } function Get-APFileCreationDate { param ( [string] $filePath, [string] $fileType ) if ($fileType -ieq "vidéo") { $propIndex = $VideoCreationDatePropIndex } if ($fileType -ieq "image") { $propIndex = $ImageCreationDatePropIndex } $charWhiteList = '[^: \w\/]' $dateTaken = (Get-APFileMetaData -FilePath $filePath -PropertyIndex $propIndex) -replace $charWhiteList $culture = Get-Culture $dateTaken = try { [DateTime]::Parse($dateTaken, $culture) } catch { $null } return $dateTaken } function _subDirectoryFromDate { param ( [string] $filePath, [Nullable[datetime]] $originalDate ) if ($originalDate) { $year = $originalDate.Year $month = $originalDate.Month.ToString("D2") $monthName = Get-Culture | ForEach-Object { $_.DateTimeFormat.GetMonthName($month) } return "$year\$month - $monthName" } else { return "Non daté" } } ########################################### #### MAIN ##### ########################################### if ($args[0] -and $args[1]) { $sourceDir = $args[0] $destinationDir = $args[1] } else { $sourceDir = Read-Host "Veuillez entrer le chemin du dossier source (ou une archive .zip)" $destinationDir = Read-Host "Veuillez entrer le chemin du dossier destination" } if ($sourceDir -imatch "\.zip$") { $tempDir = Get-APTemporaryDirectory try { Expand-Archive -LiteralPath $sourceDir -DestinationPath $tempDir $sourceDir = $tempDir }catch{ Write-Host "L'archive n'a pas pu être décompressée." return } } Get-ChildItem -Path $sourceDir -Recurse -File | ForEach-Object { $filePath = $_.FullName $fileType = (Get-APFileMetaData -File $filePath -PropertyIndex $FileTypePropIndex) if (-not($fileType -match "vidéo|image")) { Write-Host "Fichier ignoré: $($filePath)" return } $creationDate = if ($value = Get-APDateFromJson -filePath $filePath) { $value } else { Get-APFileCreationDate -filePath $filePath -fileType $fileType } $subFolder = _subDirectoryFromDate -filePath $filePath -originalDate $creationDate $targetDir = Join-Path -Path $DestinationDir -ChildPath $subFolder if (-not (Test-Path $targetDir)) { New-Item -Path $targetDir -ItemType Directory | Out-Null } Copy-Item -Path $filePath -Destination $targetDir } if ($sourceDir -like "$env:TEMP\*") { Remove-Item -Path $sourceDir -Recurse -Force }