touchコマンドの本来の使い方

この記事はImaizumi Lab Advent Calendarの24日目です。

はじめに

空のファイルを作るときに「touch hogehoge」とやりますよね。

本当はファイルのタイムスタンプを変更するためのコマンドというのは結構知られていると思いますが、じゃあどういう使い方ができるの? ということでまとめていきたいと思います。

ファイルのタイムスタンプは3種類ある

ここでちょっと遠回りして、ファイルのタイムスタンプについて解説します。

UNIX系システムのファイルのタイムスタンプには「atime」「mtime」「ctime」の3種類が存在します。*1

atimeはファイルの最終アクセス日時、mtimeはファイルの最終更新日時、ctimeはinodeが更新された日時です。inodeとは、ファイルのアクセス権や実データの場所などの属性情報のことです。

これらはstatコマンドで確認することができます。(以下、コマンドの実行例は全てUbuntuでのものです。statの出力は省略しています。MacOSだとstat -xで似たような表示になります)

$ stat a
Access: 2020-12-25 01:25:27.354297000 +0000
Modify: 2020-12-25 01:25:27.354297000 +0000
Change: 2020-12-25 01:25:27.354297000 +0000

例えば「echo "aaaa" > a」で中身を編集すると、

$ stat a
Access: 2020-12-25 01:25:27.354297000 +0000
Modify: 2020-12-25 01:25:27.354297000 +0000
Change: 2020-12-25 01:25:27.354297000 +0000
$ echo "aaaa" > a
$ stat a
Access: 2020-12-25 01:25:27.354297000 +0000
Modify: 2020-12-25 01:26:32.174235000 +0000
Change: 2020-12-25 01:26:32.174235000 +0000

のようにmtimeとctimeが更新されます。

「cat a」とすると、atimeのみが更新されます。

$ stat a
Access: 2020-12-25 01:25:27.354297000 +0000
Modify: 2020-12-25 01:26:32.174235000 +0000
Change: 2020-12-25 01:26:32.174235000 +0000
$ cat a
$ stat a
Access: 2020-12-25 01:27:59.621939000 +0000
Modify: 2020-12-25 01:26:32.174235000 +0000
Change: 2020-12-25 01:26:32.174235000 +0000

「vi a」でファイルの中身を更新すると、3つとも全て更新されます。

$ stat a
Access: 2020-12-25 01:27:59.621939000 +0000
Modify: 2020-12-25 01:26:32.174235000 +0000
Change: 2020-12-25 01:26:32.174235000 +0000
$ vi a
$ stat a
Access: 2020-12-25 01:29:46.577553000 +0000
Modify: 2020-12-25 01:29:46.577553000 +0000
Change: 2020-12-25 01:29:46.579553000 +0000

使ってみる

はじめに以下のようなファイルがあるとします。

$ ls -l
-rw-r--r-- 1 root root 6 Dec 25 01:31 a
-rw-r--r-- 1 root root 0 Dec 25 01:31 b
-rw-r--r-- 1 root root 0 Dec 25 01:31 c
$ stat a
Access: 2020-12-25 01:31:52.187919000 +0000
Modify: 2020-12-25 01:31:52.187919000 +0000
Change: 2020-12-25 01:31:52.187919000 +0000

オプションなし

「touch a」とするとaのatime、ctime、mtimeが書き換わります。

$ stat a
Access: 2020-12-25 01:31:52.187919000 +0000
Modify: 2020-12-25 01:31:52.187919000 +0000
Change: 2020-12-25 01:31:52.187919000 +0000
$ touch a
$ stat a
Access: 2020-12-25 04:13:09.531173000 +0000
Modify: 2020-12-25 04:13:09.531173000 +0000
Change: 2020-12-25 04:13:09.531173000 +0000

rオプション

「touch -r a b」とすることで、aのタイムスタンプがbのタイムスタンプになります。

$ touch -r a b
$ ls -l
-rw-r--r-- 1 root root 6 Dec 25 04:13 a
-rw-r--r-- 1 root root 0 Dec 25 04:13 b
-rw-r--r-- 1 root root 0 Dec 25 01:31 c

このオプションの使い道として、配布するソフトウェアの中身のタイムスタンプを揃えるとかがあるようです。

tオプション、dオプション

任意の時刻にタイムスタンプ(atime、mtime)を指定することができます。

$ touch -t 01011111 a
$ stat a
Access: 2020-01-01 11:11:00.000000000 +0000
Modify: 2020-01-01 11:11:00.000000000 +0000
Change: 2020-12-25 04:50:34.724411000 +0000

$ touch -d "2020-1-2 22:22" a
$ stat a
Access: 2020-01-02 22:22:00.000000000 +0000
Modify: 2020-01-02 22:22:00.000000000 +0000
Change: 2020-12-25 04:52:03.686661000 +0000

aオプション

atimeとctimeを変更することができます。

$ stat a
Access: 2020-01-02 22:22:00.000000000 +0000
Modify: 2020-01-02 22:22:00.000000000 +0000
Change: 2020-12-25 04:52:03.686661000 +0000
$ touch -a a
$ stat a
Access: 2020-12-25 04:55:19.327739000 +0000
Modify: 2020-01-02 22:22:00.000000000 +0000
Change: 2020-12-25 04:55:19.327739000 +0000

mオプション

mtimeとctimeを変更することができます。

$ stat a
Access: 2020-12-25 04:55:19.327739000 +0000
Modify: 2020-01-02 22:22:00.000000000 +0000
Change: 2020-12-25 04:55:19.327739000 +0000
$ touch -m a
$ stat a
Access: 2020-12-25 04:55:19.327739000 +0000
Modify: 2020-12-25 04:56:21.502631000 +0000
Change: 2020-12-25 04:56:21.502631000 +0000

余談:Macでのタイムスタンプの挙動が変

この記事を書くにあたってMacOSで最初試していたのですが、「cat a」したときにaのatimeが更新されるはずが更新されないという事象に遭遇してしまいました。

ディスクの書き込みを軽減させる目的でatimeの更新を無効化することがあるそうですが、調べた感じだと明示的に設定しないと有効にならないようなので、今回の場合は違うようです。

何かわかったらまた記事にしたいと思います。

*1:この他にもあるケースもありますが、本稿では取り扱いません