処理の終了やログの更新などを知るために、ファイルの最終更新時刻を参照することがある。ファイルの更新時刻を変更するには、touchコマンドがよく使われる。標準のWindows OSにはtouchはないが、同等のことは実現可能である。その方法を紹介する。
対象OS:Windows 7/Windows 8.1/Windows 10/Windows Server 2008 R2/Windows Server 2012/Windows Server 2012 R2/Windows Server 2016
Windowsシステムの管理業務やバッチなどのスクリプトを利用する場合、ファイルの最終変更時刻を、現在の時刻に更新したいことがある。
例えば、ある処理が終わった場合に特定の名前を持つファイル(例:d:\check\checkdone1.txtなど)を作成・更新するようにしておくと、後続のプログラムは、そのファイルの更新時刻情報を見て、古ければ処理を行い、新しければ(処理済みと見なして)処理をスキップする、といった判断ができるようになる。
同様にファイルを出力するプログラムがあるような場合も、何らかの理由でファイルの内容が更新されなかったとしても、取りあえず日付情報だけでも更新しておけば、正常に処理が終了したのと同じような状態になり、後続の処理を実行できるようになる。
このように、ファイルの最終変更時刻情報を見て、処理を切り替えることは少なくない。また、作成したファイルを納品する際に、全てのファイルの日付を納品日に合わせておく、といったこともよくある話だ。
LinuxやUNIXでは、ファイルの時刻情報を更新するために、「touch <ファイル名>」というコマンドが用意されている。このコマンドを実行すると、ファイルのデータ部分は何も変更せずに、ファイルの最終変更(書き込み)時刻が、現在の時刻に更新される。オプションを付ければ、現在ではなく、特定の日時にしたり、最終アクセス時刻を変更したりすることもできる。
Windows OSのバッチなどでもこのような最終変更時刻の更新を行いたいことがあるが、残念ながらtouchコマンドはデフォルトでは用意されていない。だが、類似の機能を実現することは可能である。本TIPSでは、このような方法を幾つか紹介する。
なおtouchコマンドには、「存在しないファイル名を指定した場合は、長さ0バイトの空ファイルを作成する」という機能があるが、そのような使い方については次のTIPSを参照していただきたい。
コマンドプロンプトにはcopyという内部コマンドがあり、通常はファイルをコピーするために使われる。だが「 + 」(プラス)記号でファイル名を複数連結して並べると、ファイルを「結合」できる。結合されたファイルの最終変更時刻は、当然、このコマンドを実行した時刻になる。
※file1.txtとfile2.txtを結合して、file3.txtに保存する
copy file1.txt+file2.txt file3.txt
※宛先を省略すると、先頭のファイル(file1.txt)に後続のファイル(file2.txt)が追加される
copy file1.txt+file2.txt
【注意】copyの「+」でファイルを結合すると、デフォルトではテキストモードで結合される(/aオプションを付けたのと同じ)。結合するテキストデータの途中にEOF文字(End Of File、Ctrl-Z、16進数なら0x1a)があると、そこまでしかコピーされないし、UnicodeのBOMがあれば削除されることがある。ファイル全体をデータとしてそのまま全て結合するには、/bオプションを先頭に付けてバイナリモードにすること。
この機能を使って、「対象ファイルに、空のデータを追加する」と、ファイルの最終変更時刻情報を更新できる。具体的には次のようにする。
※file1.txtに空のデータを追加して更新する。ファイル名の最後にプラス記号を付けるだけ
copy file1.txt+
追加するファイル名が省略されているが、この場合は空ファイル(nulデバイス)が追加されたのと等価になる。
実際に実行すると次のようになる。
これでtouchコマンドと似たようなことができるが、いくつか注意点がある。
なお古いMS-DOS時代のcopyコマンドの場合は、先頭に/bを付けてバイナリモードでのコピーを強制しないと、EOF以降がコピーされずにファイルが短くなることがあった。だが本TIPSで対象にしているOS(Windows 7以降)なら、ファイル名が1つの場合は/bオプションなしでも問題ないようである。念のために/bオプションを付けるなら、「copy /b new.txt+」のように、先頭に付けておく。
PowerShellの場合は、Set-ItemPropertyコマンドレットでファイルの時刻情報を変更できる。
※書式
Set-ItemProperty -Path <ファイル名> -Name LastWriteTime -Value $(Get-Date)
省略すると
Set-ItemProperty <ファイル名> LastWriteTime $(Get-Date)
もしくは
sp <ファイル名> LastWriteTime $(Get-Date)
次の構文も可
dir <ファイル名> | % { $_.LastWriteTime = $(Get-Date) }
「LastWriteTime」(最終変更時刻)以外にも、「LastAccessTime」(最終アクセス時刻)、「CreationTime」(作成時刻)も指定できる。
実行すると次のようになる。
現在時刻ではなく任意の日時に変更するには、「$(Get-Date)」の代わりに「"2001/01/01"」や「"2018/10/11 12:34:56"」のように日付や日時を指定する。
LinuxやUNIXのtouchコマンドを使いたいなら、Linuxで提供されているtouchコマンドをWindows OS上で呼び出せばよい。Windows OS向けに移植されたtouchコマンドも多数あるが、Windows 10ならWSL(Windows Subsystem for Linux)上のtouchコマンドを呼び出すとよいだろう。
上記のTIPSを参考にWSLをWindows 10上で利用できるようにしてからbash上で実行するか、コマンドプロンプト上で先頭に「wsl」を付けて「wsl touch <ファイル名>」のようにして呼び出せばよい。
更新時間情報を指定した日時に変更するには、「-t YYYYMMDDhhmm」か「-d "YYYY/MM/DD hh:mm"」オプションを使って日時を指定すればよい(hhmmやhh:mmの部分を省略すると00:00になる)。例えば「touch -t 201901021234 lock.lck」のようにする。
Copyright© Digital Advantage Corp. All Rights Reserved.