-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathSet photo dates.ps1
153 lines (124 loc) · 3.95 KB
/
Set photo dates.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#requires -version 3
<#
Get date created from image file metadata and set as the file's creation time
Some code from https://nicholasarmstrong.com/2010/02/exif-quick-reference/
@guyrleech 2019
#>
<#
.SYNOPSIS
Get the date/time created from image file metadata and set as the file's creation date/time
.DESCRIPTION
Note that generally only pictures taken with a digital camera will have the picture's creation time set in the file's metadata
.PARAMETER folders
A comma separated list of folder names to operate on
.PARAMETER files
A comma separated list of file names to operate on
.PARAMETER recurse
If specified will resource each of the given folders otherwise only the top level files are processed
.EXAMPLE
& '.\Set photo dates.ps1' -folders $env:userprofile\Pictures,f:\photos -recurse
Examine all files in the two folders given, and subfolders, and change the creation date to that found within the file's metadata, if present.
#>
[CmdletBinding()]
Param
(
[Parameter(ParameterSetName='Folders')]
[string[]]$folders ,
[Parameter(ParameterSetName='Files')]
[string[]]$files ,
[Parameter(ParameterSetName='Folders')]
[switch]$recurse
)
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Text")
Function Set-PhotoDate
{
[CmdletBinding()]
Param
(
[string]$filename
)
Write-Verbose "Examining `"$filename`" ..."
try
{
$photo = [System.Drawing.Image]::FromFile( $filename )
}
catch
{
## probably not a graphics file
Write-Warning "Failed to get open file `"$filename`""
$photo = $null
}
if( $photo )
{
$result = $null
try
{
$dateProperty = $photo.GetPropertyItem( 0x9003 )
}
catch
{
Write-Warning "Failed to get date property from file `"$filename`""
$dateProperty = $null
}
if( $dateProperty )
{
[string]$dateTaken = (New-Object System.Text.UTF8Encoding).GetString( $dateProperty.Value )
if( ! [string]::IsNullOrEmpty( $dateTaken ) )
{
## Seems it can get a trailing NULL character so strip this off
while( $dateTaken.Length -and [int]$dateTaken[-1] -eq 0 )
{
$dateTaken = $dateTaken.Substring( 0 , $dateTaken.Length - 1 )
}
$result = New-Object DateTime
if( ! [datetime]::TryParseExact(
$dateTaken ,
'yyyy:MM:dd HH:mm:ss' ,
[System.Globalization.CultureInfo]::InvariantCulture,
[System.Globalization.DateTimeStyles]::None,
[ref]$result) )
{
Write-Warning "Failed to parse date `"$dateTaken`" from `"$filename`""
$result = $null
}
}
}
$photo.Dispose() ## need to ensure not in use otherwise can't update
$photo = $null
if( $result )
{
$properties = Get-ItemProperty -Path $filename
if( $properties )
{
if( $properties.CreationTime -ne $result )
{
$properties.CreationTime = $result
}
}
}
}
}
if( $PSBoundParameters[ 'folders' ] )
{
ForEach( $folder in $folders )
{
Get-ChildItem -Path $folder -File -Recurse:$recurse | . `
{
Process `
{
Set-PhotoDate -filename $_.FullName
}
}
}
}
elseif( $PSBoundParameters[ 'files' ] )
{
$files | . `
{
Process `
{
Set-PhotoDate -filename $_
}
}
}