■ JPEG更新日時一括変更ツールを作る #3

#2 からの続き

本文中の "$" は半角で読み替えること。


ファイル名先頭13桁を取得

ファイル名先頭13桁(YYYYMMDD_HHMM)が日時であるので、先頭13桁を取得する。
取得するには $file.Name に対して Substring(0, 13) と書く。
先頭の引数 "0" は取得開始位置(開始位置は0から始まる)、2番目の引数は取得する文字数なので 13 を指定する。
$file.Name.Substring(0, 13)

日付型へ変更

取得した"YYYYMMDD_HHMM" 形式の文字列を日付型へ変更する。
日付型へ変更するには [DataTime] でキャストすれば良い。
また、今回の書式を.NETの形式で表すと "yyyyMMdd_HHmm" となる。
書式を使い日付型へ変更する場合は "[DateTime]::ParseExact( 文字列, 書式, 書式プロバイダ )" で可能。
書式プロバイダは、とりあえず "$null" と指定すれば良いようだ。
そして、取得した日付型を $fileDate 変数へ格納しておく。
$fileDate = [DateTime]::ParseExact($file.Name.Substring(0, 13), "yyyyMMdd_HHmm", $null)

作成日時と更新日時

ファイルのプロパティを見ると、ファイルの変更を示す値として "作成日時" と "更新日時" の2つがある。
Googleフォトは、どちらを参照して分類してるんだろうか。

試しに、
・作成日時:2020年9月8日
・更新日時:2020年9月1日
のファイルをGoogleフォトにアップしたところ、9月1日に分類された。
ということで、今回のツールは更新日時を変更すれば良さそうである。

更新日時の変更

ファイル名より取得した日時でJPEGファイルの更新日時を更新する。
ファイルプロパティの変更は Set-ItemProperty コマンドレットで行う。
このコマンドレットは、対象のファイル名、そしてプロパティ名(-Name)とプロパティ値(-Value)を指定する。

ファイル名は念のためフルパス指定する。フルパスは $file.FullName で取得できる。
更新日時のプロパティ名は "LastWriteTime" であり、プロパティ値は取得した日時となる。
Set-ItemProperty $file.FullName -Name LastWriteTime -Value $fileDate

エラー処理と結果の表示

正常終了したファイルは "[OK] ファイル名" を表示し、
ファイル名より取得した日時が不正な値だった、またファイルへの書き込みができなかった場合などエラーが発生した場合は、
"[ER] ファイル名" と 次の行にエラー内容を表示させ、次のファイルの処理に進むようにする。

PowerShellの例外処理は .NETなど一般の言語と同じ Try ~ Catch を使う。
例外オブジェクトはCatch内で $_ 変数で取得する。
画面への表示は Write-Host コマンドレットで行い、改行は "`r`n" で行う。

これらすべてをまとめると以下のスクリプトとなった。
Param([Parameter(mandatory=$true)][String]$inputDir)

$files = Get-ChildItem -Path $inputDir | Where-Object {$_.Name -Match "^\d{8}_\d{4}_[^.]*\.jpeg"}

foreach ($file in $files)
{
  try {
    $fileDate = [DateTime]::ParseExact($file.Name.Substring(0, 13), "yyyyMMdd_HHmm", $null)
    Set-ItemProperty $file.FullName -Name LastWriteTime -Value $fileDate
    Write-Host( "[OK] " + $file.Name)
  } catch {
    Write-Host( "[ER] " + $file.Name + "`r`n" + $_)
  }
}


Googleフォトにアップした際、画像の時刻が -9時間される(おそらくUTCの時刻で計算される)現象が発生した。
回避策を検討中。


#4 へ続く


自作プログラム, PowerShell

0 件のコメント:

その他の記事