PowerShellとファイルの日付についてちょっとしたこと
PowerShellを使うとファイルやフォルダーの日付を簡単に変更できますが、
(Get-Item c.txt).LastWriteTime = '2012/3/4 5:6:7'
ちゃんと小数点以下まで指定しないと、日付を変更したことがばれます。
Get-Item *.txt | Select-Object Name,{$_.LastWriteTime.ToString('yyyy/MM/dd HH:mm:ss.fffffff')}
少し前に、証拠データの日付を書き換えた検察官がいて問題になったことがあります。遠隔操作ウイルス事件もそうですが、日本ではあまりフォレンジックとかやらないんでしょうか。
どれくらい昔の日付に設定できる?
ウィキペディアで調べるとNTFSはファイルの日付を1601年1月1日 0時0分0秒 (UTC) から100ナノ秒単位で保持しているようです。論理的にはこの日付に設定できるはずですが、実際にやってみるとできません。
(Get-Item c.txt).LastWriteTimeUtc = '1601/1/1'
これはWindowsAPIの仕様で、SetFileTime関数に基点となる日付からきっかり 0 秒後が指定されるとスルーされてしまうのです *1。そういうわけで、0時0分0.0000001秒が、設定できる最も古い日付ということになります。
(Get-Item c.txt).LastWriteTimeUtc = '1601/1/1 0:0:0.0000001'
ところで、C言語のFILETIME構造体と.NETのDateTime構造体は少し仕様が違います。分解能は同じですが、後者は基点が西暦1年になっています *2。なので、PowerShell側で以下のような日付を作ることは可能ですが、
$dt = [datetime] '0001/1/1'
この日付をNTFSのファイルに指定するとWin32エラーになるのはそういう理由です。
(Get-Item c.txt).LastWriteTimeUtc = $dt # "LastWriteTimeUtc" の設定中に例外が発生しました: # "有効な Win32 FileTime ではありません。"
以上です。
*1:そもそもPowerShellはSetFileTime関数を使っているのかという疑問がありますが、少なくとも Process Monitor で見る限り呼び出しているようです。また、FILETIME構造体も日付の仕様はNTFSと同じです。
*2:http://referencesource.microsoft.com/#mscorlib/system/datetime.cs,131 コメントより