いつものしらべてもでてこない

調べた事を書きます

ファイルの日付文字列から更新日時や作成日時をPowerShellを利用して一括変更する方法。フリーソフト。

スマホでファイルを移動していたら更新日時が書き換えられて写真の並び順がばらばらになってしまった。
どうやら本体の内蔵メモリからSDカードの様な別のデバイスに移動すると更新日時が再設定されるようだ。
これをPowerShellを利用して一括変更する方法。

概要

Android等のスマホのファイルをSDカードに移動した上でスマホから取り出してPC上でPoweShellのファイルを実行して更新日時を変更します。
直接変更はadb shellを使えば出来るでしょうが一括処理はやや難しいと思います。
以前の記事の改良版になります。

以前の記事もご覧下さい。
bannan.hatenadiary.jp

PowerShellで一括変更。

フリーソフトと書いてありますがプログラムをコピペしてPowerShellスクリプトファイルを作成します。
フォルダ内の該当ファイルのみ変更しフォルダについては変更しません。

ファイル名について

ファイル名から日時を設定するのでファイル名に日時の文字列が必要です。
一般的な YYYY-MM-DD_HH-MM-SS と言う様な形式になります。
様なと言うのは正規表現を利用して数値の間の接続文字はあってもなくても良い様にしてあるので桁数さえ合えば変更処理が出来るようにしています。(例、photo_2020w3i4_5432-01.jpg)
ファイル名の変更については以前の記事のFlexbleRenamerの部分をご覧下さい。

PowerShellについて

作成するフリーソフト?はテキストファイルにコピペして拡張子を.ps1に変更するだけのものです。
署名無しのPowerShellを使用する設定をした事が無い場合は右クリックから実行できません。
詳しくは説明しませんが「検索」か「エクスプローラーのアドレスバー」にPowerShellと打ち込んで「Enterキー」を押し起動したら Set-ExecutionPolicy RemoteSignedを入力して「Enterキー」を押 しておけば大丈夫だと思います。
RemoteSignedに設定するとセキュリティ上の危険性が少し高くなります、その為実行後は元の設定かRestrictedに変更しておく事をお勧めします。


PowerShellを使用する設定についてはこちらをご覧下さい。
technet.microsoft.com

www.atmarkit.co.jp


管理者権限が必要な場合はPowerShellCtrl+Shift+ENTER で管理者権限で起動して実行するか一時的にUACを切る等してください。

interprism.hatenablog.com

PowerShellのコード

デスクトップかエクスプローラーの右側の空白の適当な所を右クリックしてテキストファイルを作成してください。
テキストファイルを作成したら下のコードをドラッグして選択し右クリックメニューからコピーを選んでテキストファイルの方に貼り付けてください。
貼り付けたらファイル名と拡張子を TouchMe.ps1 に変更してください。
拡張子が表示されていない場合はエクスプローラーの設定で「登録されている拡張子は表示しない」のチェックを外してください。

拡張子を表示する方法
https://support.microsoft.com/ja-jp/help/978449


コード

# This program is to set "CreationTime" and "LastWriteTime" with DateTime from Filename.

$args = Get-ChildItem -Path *;
foreach ($arg in $args) {
 # exclude directory
 if($arg.GetType().Name -eq "FileInfo"){
 # regular expressions, name + datetime + dot + file extension.
  $regex = [regex]"^.*(\d{4})[^\d]?0?(\d|\d{2})[^\d]?0?(\d|\d{2})[^\d]?(\d{2})[^\d]?(\d{2})[^\d]?(\d{2})\..*";
  $m = $regex.Matches($arg);
  if($m[0] -ne $null){
    # validation
   $num = [Int]("{0,0:#}" -f $m[0].Groups[2]);
   if($num -lt 1 -Or $num -gt 12){
    Write-Output("$arg : $num is not valid month.")
    continue;
   }
   $num = [Int]("{0,0:#}" -f $m[0].Groups[3]);
   if($num -lt 1 -Or $num -gt 31){
    Write-Output("$arg : $num is not valid day.")
    continue;
   }
   $num = [Int]("{0,0:#}" -f $m[0].Groups[4]);
   if($num -lt 0 -Or $num -gt 23){
    Write-Output("$arg : $num is not valid hour.")
    continue;
   }
   $num = [Int]("{0,0:#}" -f $m[0].Groups[5]);
   if($num -lt 0 -Or $num -gt 59){
    Write-Output("$arg : $num is not valid minute.")
    continue;
   }
   $num = [Int]("{0,0:#}" -f $m[0].Groups[6]);
   if($num -lt 0 -Or $num -gt 61){
    Write-Output("$arg : $num is not valid second.")
    continue;
   }
   # end of validation
   
   # datetime
   $dtime = "{0,0:#}/{1,0:#}/{2,0:#} {3,2:##}:{4,2:##}:{5,2:##}" -f $m[0].Groups[1], $m[0].Groups[2], $m[0].Groups[3], $m[0].Groups[4], $m[0].Groups[5], $m[0].Groups[6];
   Write-Output("$arg set $dtime");
   # 作成日時を設定
   Set-ItemProperty $arg -name CreationTime -value $dtime;
   # 更新日時を設定
   Set-ItemProperty $arg -name LastWriteTime -value $dtime;
  }
 }
}

コード終わり。

日付のチェック処理で01の様な文字をSystem.Text.RegularExpression.MatchCollection型からInt型にキャストする方法がどうにも見つからなかった為、正規表現で01の様な数字の場合に先頭の0を無視する形式で文字を取り出して型変換エラーを出さないようにしているが後ろの3グループの数字についてはしていない。

使い方

PowerShellスクリプト.ps1ファイルを変更したいファイルがあるフォルダにコピー又は移動して右クリックしメニューからから「実行」をクリックするだけです。

これをPowerShell上から実行したい場合は該当フォルダを開いて「アドレスバーの空欄部分」をクリックし PowerShell と入力して「Enterキー」を押してPowerShellを起動してください。
PowerShellスクリプトのファイル名を打ち込んで「Enterキー」を押し実行すると変更のログを見る事が出来ます
その際は出力結果をテキストファイルにリダイレクトしておくと便利です。
TouchMe.ps1 > TouchLog.txt

日付が変なファイルがあるとログに残るのでわかります。
ログに出ないファイルは名前を見て日付となる数字が見つからなかったファイルです。

注意

フォルダ内の日付変更のみのプログラムで動作確認はしてありますがPowerShellの実行許可も含め自己責任でお願いします。


処理がすっきりした。
以上。