3 Commits

Author SHA1 Message Date
  Figg b8a96cfa0a Merge branch 'master' of https://git.eseb.ovh/Figg/PicturesArrangerScript 1 month ago
  Figg 20342e34d5 Big code refactoring to improve readability and maintenance 1 month ago
  Figg 81dfbab939 Readme + gitignore small rewritings 1 month ago
3 changed files with 61 additions and 86 deletions
  1. 0
    1
      .gitignore
  2. 53
    79
      ArrangePictures.ps1
  3. 8
    6
      README.md

+ 0
- 1
.gitignore View File

1
 # Ignore test files
1
 # Ignore test files
2
-/Out
3
 /Test/*
2
 /Test/*
4
 
3
 
5
 # Except files provided as Mockup
4
 # Except files provided as Mockup

+ 53
- 79
ArrangePictures.ps1 View File

1
-# Fonction pour récupérer une Array des extensions d'images et vidéos depuis un json
2
-function Get-ImageVideoExtensions {
1
+function Get-APImageVideoExtensions {
3
     param (
2
     param (
4
         [string] $sourceUrl = "https://cdn.jsdelivr.net/gh/jshttp/mime-db@v1.52.0/db.json"
3
         [string] $sourceUrl = "https://cdn.jsdelivr.net/gh/jshttp/mime-db@v1.52.0/db.json"
5
     )
4
     )
7
     $extensions = @()
6
     $extensions = @()
8
 
7
 
9
     foreach ($item in $jsonData) {
8
     foreach ($item in $jsonData) {
10
-        if ($item.Name -like "image*" -or $item.Name -like "video*") {
9
+        if ($item.Name -match "^(image|video)") {
11
             $extensions += $item.Value.extensions
10
             $extensions += $item.Value.extensions
12
         }
11
         }
13
     }
12
     }
16
     return $extensions
15
     return $extensions
17
 }
16
 }
18
 
17
 
19
-# Fonction pour décompresser les archives
20
-function Decompress-ArchiveIfNeeded {
21
-    param(
22
-        [string]$ArchivePath,
23
-        [string]$ExtractPath
18
+function Get-APFileDateTaken {
19
+    param (
20
+        [string] $FilePath
24
     )
21
     )
22
+    $Folder = (New-Object -ComObject Shell.Application).NameSpace((Split-Path $FilePath))
23
+    $PropIndex = 12  # Date Taken Property Index
24
+    $CharWhiteList = '[^: \w\/]'
25
+
26
+    $DateTaken = $Folder.GetDetailsOf(
27
+        $Folder.ParseName((Split-Path -Leaf $FilePath)),
28
+        $PropIndex
29
+    ) -replace $CharWhiteList
30
+
25
     
31
     
26
-    if (Test-Path $ArchivePath -PathType Leaf) {
27
-        $tempDir = Join-Path -Path $ExtractPath -ChildPath ([System.IO.Path]::GetRandomFileName())
28
-        while (Test-Path $tempDir) {
29
-            $tempDir = Join-Path -Path $ExtractPath -ChildPath ([System.IO.Path]::GetRandomFileName())
30
-        }
31
-        New-Item -Path $tempDir -ItemType Directory | Out-Null
32
-        Expand-Archive -Path $ArchivePath -DestinationPath $tempDir
33
-        return $tempDir
34
-    }
35
-    return $null
32
+    $DateTaken = try { [DateTime]($DateTaken) } catch { $null }
33
+    return $DateTaken
34
+}
35
+
36
+function Get-APTemporaryDirectory {
37
+    do {
38
+        $TempDir = Join-Path -Path $env:TEMP -ChildPath ([System.IO.Path]::GetRandomFileName())
39
+    } while (Test-Path $TempDir)
40
+    return $TempDir
36
 }
41
 }
37
 
42
 
38
-# Fonction pour obtenir la date de création d'une image/vidéo
39
-function Get-OriginalDate {
43
+function Get-APCreationDateSubDirectory {
40
     param (
44
     param (
41
-        $file
45
+        [string] $filePath
42
     )
46
     )
43
-    # Tentative de lecture des données EXIF
44
-    $exif = Try { [System.Drawing.Image]::FromFile($file.FullName) } Catch { $null }
45
 
47
 
46
-    if ($exif) {
47
-        $exifDate = $exif.PropertyItems | Where-Object { $_.Id -eq 0x9003 } | ForEach-Object {
48
-            [System.Text.Encoding]::ASCII.GetString($_.Value).TrimEnd([char]0)
49
-        }
50
-        if ($exifDate) {
51
-            $date = [datetime]::ParseExact($exifDate, "yyyy:MM:dd HH:mm:ss", $null)
52
-        } else {
53
-            $date = $file.CreationTime
54
-        }
55
-        $exif.Dispose()
48
+    $originalDate = Get-APFileDateTaken -FilePath $filePath
49
+
50
+    if ($originalDate) {
51
+        $year = $originalDate.Year
52
+        $month = $originalDate.Month.ToString("D2")
53
+        $monthName = Get-Culture | ForEach-Object { $_.DateTimeFormat.GetMonthName($month) }
54
+
55
+        return "$year\$month - $monthName"
56
     } else {
56
     } else {
57
-        $date = $file.CreationTime
57
+        return "Non daté"
58
     }
58
     }
59
 }
59
 }
60
 
60
 
61
-# Demande des paramètres si non fournis
62
 if (-not $args[0] -or -not $args[1]) {
61
 if (-not $args[0] -or -not $args[1]) {
63
-    $SourceDir = Read-Host "Entrez le chemin du dossier source"
64
-    $DestinationDir = Read-Host "Entrez le chemin du dossier destination"
62
+    $SourceDir = Read-Host "Veuillez entrer le chemin du dossier source (ou une archive .zip)"
63
+    $DestinationDir = Read-Host "Veuillez entrer le chemin du dossier destination"
65
 } else {
64
 } else {
66
     $SourceDir = $args[0]
65
     $SourceDir = $args[0]
67
     $DestinationDir = $args[1]
66
     $DestinationDir = $args[1]
68
 }
67
 }
69
 
68
 
70
-# Vérifie si le dossier source est une archive
71
-if ($SourceDir -match "\.zip$") {
72
-    $SourceDir = Decompress-ArchiveIfNeeded -ArchivePath $SourceDir -ExtractPath $env:TEMP
73
-    if (-not $SourceDir) {
69
+if ($SourceDir -imatch "\.zip$") {
70
+    $TempDir = Get-APTemporaryDirectory
71
+
72
+    try {
73
+        Expand-Archive -Path $SourceDir -DestinationPath $TempDir
74
+        $SourceDir = $TempDir
75
+    }catch{
74
         Write-Host "L'archive n'a pas pu être décompressée."
76
         Write-Host "L'archive n'a pas pu être décompressée."
75
         return
77
         return
76
     }
78
     }
77
 }
79
 }
78
 
80
 
79
-$validExtensions = Get-ImageVideoExtensions
80
-
81
-# Parcourt tous les fichiers récursivement dans le dossier source
81
+$ValidExtensions = Get-APImageVideoExtensions
82
 Get-ChildItem -Path $SourceDir -Recurse -File | ForEach-Object {
82
 Get-ChildItem -Path $SourceDir -Recurse -File | ForEach-Object {
83
-    $file = $_
84
-    $extension = $file.Extension.ToLower().TrimStart('.')
85
-
86
-    if ($extension -in $validExtensions) {
87
-        # Tentative de lecture des données EXIF
88
-        $exif = Try { [System.Drawing.Image]::FromFile($file.FullName) } Catch { $null }
89
-
90
-        if ($exif) {
91
-            $exifDate = $exif.PropertyItems | Where-Object { $_.Id -eq 0x9003 } | ForEach-Object {
92
-                [System.Text.Encoding]::ASCII.GetString($_.Value).TrimEnd([char]0)
93
-            }
94
-            if ($exifDate) {
95
-                $originalDate = [datetime]::ParseExact($exifDate, "yyyy:MM:dd HH:mm:ss", $null)
96
-            } else {
97
-                $originalDate = $file.CreationTime
98
-            }
99
-            $exif.Dispose()
100
-        } else {
101
-            $originalDate = $file.CreationTime
102
-        }
103
-        
104
-        if (-Not $originalDate) {
105
-            $targetFolder = Join-Path -Path $DestinationDir -ChildPath "Non daté"
106
-        } else {
107
-            # Créer le dossier de destination basé sur l'année et le mois
108
-            $year = $originalDate.Year
109
-            $monthNum = $originalDate.Month.ToString("00")
110
-            $monthName = $originalDate.ToString("MMMM", [System.Globalization.CultureInfo]::GetCultureInfo("fr-FR"))
111
-            $targetFolder = Join-Path -Path $DestinationDir -ChildPath "$year\$monthNum - $monthName"
112
-        }
83
+    $File = $_
84
+    $FileExtension = $File.Extension.ToLower().TrimStart('.')
85
+
86
+    if ($ValidExtensions -contains $FileExtension) {
87
+        $subFolder = Get-APCreationDateSubDirectory -filePath $File.FullName
88
+        $targetDir = Join-Path -Path $DestinationDir -ChildPath $subFolder
113
 
89
 
114
-        if (-Not (Test-Path $targetFolder)) {
115
-            New-Item -Path $targetFolder -ItemType Directory | Out-Null
90
+        if (-not (Test-Path $targetDir)) {
91
+            New-Item -Path $targetDir -ItemType Directory | Out-Null
116
         }
92
         }
117
 
93
 
118
-        # Copier le fichier dans le dossier de destination
119
-        Copy-Item -Path $file.FullName -Destination $targetFolder
94
+        Copy-Item -Path $file.FullName -Destination $targetDir
120
     } else {
95
     } else {
121
         Write-Host "Fichier ignoré: $($file.FullName)"
96
         Write-Host "Fichier ignoré: $($file.FullName)"
122
     }
97
     }
123
 }
98
 }
124
 
99
 
125
-# Suppression du dossier temporaire si nécessaire
126
 if ($SourceDir -like "$env:TEMP\*") {
100
 if ($SourceDir -like "$env:TEMP\*") {
127
     Remove-Item -Path $SourceDir -Recurse -Force
101
     Remove-Item -Path $SourceDir -Recurse -Force
128
 }
102
 }

+ 8
- 6
README.md View File

1
 # PicturesArranger
1
 # PicturesArranger
2
 
2
 
3
-Ce script Powershell récupère les fichiers images/vidéos contenus dans une source et les copie dans une destination en les rangeant selon une arborescence qui se base sur la date de création des fichiers.
3
+Ce script Powershell récupère les fichiers images et vidéos contenus dans une source et les copie dans une destination en les rangeant selon une arborescence qui se base sur la date de création des fichiers.
4
 
4
 
5
-Je l'utilise pour trier d'un bloc toutes mes données dans mon SSD externe.
5
+Je l'utilise pour trier d'un bloc tous mes médias Google Photos dans un SSD externe.
6
 
6
 
7
 ## Utilisation
7
 ## Utilisation
8
 
8
 
10
 
10
 
11
 ![Illustration.](https://git.eseb.ovh/Figg/PicturesArrangerScript/raw/branch/master/images/readme_img1.png "Exécuter avec Powershell")
11
 ![Illustration.](https://git.eseb.ovh/Figg/PicturesArrangerScript/raw/branch/master/images/readme_img1.png "Exécuter avec Powershell")
12
 
12
 
13
-Il vous demandera deux chemins ; Le premier vers le dossier source ou récupérer les fichiers, vous pouvez aussi lui donner une archive qu'il décompressera le temps de l'exécution, le deuxième vers le dossier destination ou ranger les images récupérées, il le créera si besoin.
13
+Il vous demandera deux chemins comme paramètres : 
14
+- Le premier vers le dossier source où récupérer les fichiers, vous pouvez aussi lui donner une archive au format .zip qu'il décompressera le temps de l'exécution.
15
+- Le deuxième vers le dossier destination où ranger les images et vidéos récupérées.
14
 
16
 
15
-Vos fichiers rangées dans des sous-dossiers par année puis par mois en se basant sur la date où le fichier a été créé pour la première fois.
16
-Par exemple "2023\\03 - Mars\\"
17
+Vos fichiers qui auront été identifiés comme image ou vidéo seront répartis dans des sous-dossiers par année puis par mois en se basant sur la date où ils ont été créés pour la première fois.
18
+Par exemple "*2023\\03 - Mars\\*"
17
 
19
 
18
-Il arrive que certains fichiers ne puissent être datés et soient rangés dans un dossier "Non daté"
20
+Il arrive que certains fichiers ne puissent être datés et soient rangés dans un dossier "*Non daté*"

Loading…
Cancel
Save