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,5 +1,4 @@
1 1
 # Ignore test files
2
-/Out
3 2
 /Test/*
4 3
 
5 4
 # Except files provided as Mockup

+ 53
- 79
ArrangePictures.ps1 View File

@@ -1,5 +1,4 @@
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 2
     param (
4 3
         [string] $sourceUrl = "https://cdn.jsdelivr.net/gh/jshttp/mime-db@v1.52.0/db.json"
5 4
     )
@@ -7,7 +6,7 @@ function Get-ImageVideoExtensions {
7 6
     $extensions = @()
8 7
 
9 8
     foreach ($item in $jsonData) {
10
-        if ($item.Name -like "image*" -or $item.Name -like "video*") {
9
+        if ($item.Name -match "^(image|video)") {
11 10
             $extensions += $item.Value.extensions
12 11
         }
13 12
     }
@@ -16,113 +15,88 @@ function Get-ImageVideoExtensions {
16 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 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 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 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 64
 } else {
66 65
     $SourceDir = $args[0]
67 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 76
         Write-Host "L'archive n'a pas pu être décompressée."
75 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 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 95
     } else {
121 96
         Write-Host "Fichier ignoré: $($file.FullName)"
122 97
     }
123 98
 }
124 99
 
125
-# Suppression du dossier temporaire si nécessaire
126 100
 if ($SourceDir -like "$env:TEMP\*") {
127 101
     Remove-Item -Path $SourceDir -Recurse -Force
128 102
 }

+ 8
- 6
README.md View File

@@ -1,8 +1,8 @@
1 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 7
 ## Utilisation
8 8
 
@@ -10,9 +10,11 @@ Vous pouvez lancer le script depuis l'explorateur de fichiers Windows en faisant
10 10
 
11 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