Windows OSでファイルの最終変更時刻を更新する(touchコマンドを実現する)Tech TIPS

処理の終了やログの更新などを知るために、ファイルの最終更新時刻を参照することがある。ファイルの更新時刻を変更するには、touchコマンドがよく使われる。標準のWindows OSにはtouchはないが、同等のことは実現可能である。その方法を紹介する。

» 2018年09月13日 05時00分 公開
[打越浩幸デジタルアドバンテージ]
「Tech TIPS」のインデックス

連載目次

対象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コマンドでファイルの最終変更時刻を更新する

 コマンドプロンプトには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)があると、そこまでしかコピーされないし、UnicodeBOMがあれば削除されることがある。ファイル全体をデータとしてそのまま全て結合するには、/bオプションを先頭に付けてバイナリモードにすること。

 この機能を使って、「対象ファイルに、空のデータを追加する」と、ファイルの最終変更時刻情報を更新できる。具体的には次のようにする。

※file1.txtに空のデータを追加して更新する。ファイル名の最後にプラス記号を付けるだけ
copy file1.txt+



 追加するファイル名が省略されているが、この場合は空ファイル(nulデバイス)が追加されたのと等価になる。

 実際に実行すると次のようになる。

コマンドプロンプト上のcopyコマンドでファイルの変更時刻を更新する コマンドプロンプト上のcopyコマンドでファイルの変更時刻を更新する
copyコマンドのファイル結合機能を使って空のデータを追加すると(ファイル名の最後にプラス記号を付けるだけ)、更新時刻情報を現在の時刻に更新できる。

 これでtouchコマンドと似たようなことができるが、いくつか注意点がある。

  • 対象のファイル(上の例ではnew.txt)が存在しない場合はエラーになるので、必要ならば、最初に空のファイルを作成しておくこと
  • 対象ファイルがカレントディレクトリ以外にある場合は、最終的なファイルがカレントディレクトリ中に作成され、元のファイルは何も変更されない(「copy c:\log\file1.txt」のような使い方は、してはいけないということ)。対象ファイルには、パス名を付けずに済むように、最初にcdで対象フォルダ位置へ移動するなどの対策が必要
  • ファイルの最終変更時刻を任意の時刻にすることはできず、現在の時刻に更新することだけが可能

 なお古いMS-DOS時代のcopyコマンドの場合は、先頭に/bを付けてバイナリモードでのコピーを強制しないと、EOF以降がコピーされずにファイルが短くなることがあった。だが本TIPSで対象にしているOS(Windows 7以降)なら、ファイル名が1つの場合は/bオプションなしでも問題ないようである。念のために/bオプションを付けるなら、「copy /b new.txt+」のように、先頭に付けておく。

PowerShellのSet-ItemPropertyコマンドレットでファイルの最終変更時刻を変更する

 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」(作成時刻)も指定できる。

 実行すると次のようになる。

PowerShellのSet-ItemPropertyでファイルの変更時刻を更新する PowerShellのSet-ItemPropertyでファイルの変更時刻を更新する
Set-ItemPropertyコマンドレットを使うと、時刻情報やファイルの属性などを変更できる。

 現在時刻ではなく任意の日時に変更するには、「$(Get-Date)」の代わりに「"2001/01/01"」や「"2018/10/11 12:34:56"」のように日付や日時を指定する。

WSLのtouchコマンドを呼び出す

 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 <ファイル名>」のようにして呼び出せばよい。

touchコマンドでファイルの変更時刻を更新する touchコマンドでファイルの変更時刻を更新する
WSLのUbuntu上でtouchコマンドを使っているところ。やはり本家本元のtouchコマンドがシンプルで分かりやすい。

 更新時間情報を指定した日時に変更するには、「-t YYYYMMDDhhmm」か「-d "YYYY/MM/DD hh:mm"」オプションを使って日時を指定すればよい(hhmmhh:mmの部分を省略すると00:00になる)。例えば「touch -t 201901021234 lock.lck」のようにする。

「Tech TIPS」のインデックス

Tech TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。