「このファイル、最後にいじったのはいつだったか」。運用中のサーバーで、そう振り返りたくなる場面がときどきあります。
ところが ls -l の1行では、サイズと更新日時までしか分かりません。
権限をいつ書き換えたのかまで追いたくなったとき、私が手を伸ばすのが stat という小さなコマンドでした。
statは「ls -l の詳しい版」
stat は、ファイルやディレクトリのメタ情報をまとめて表示するコマンドです。
パスを渡すだけで、サイズ・inode 番号・パーミッション・所有者・各種タイムスタンプが一気に並びます。
$ stat note.txt
File: note.txt
Size: 6 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 21364 Links: 1
Access: (0644/-rw-r--r--) Uid: (1470/kamome) Gid: (1470/kamome)
Access: 2026-08-08 20:54:15.431031927 +0900
Modify: 2026-08-08 20:54:15.431031927 +0900
Change: 2026-08-08 20:54:15.436031927 +0900
Birth: 2026-08-08 20:54:15.431031927 +0900
この記事の出力は、すべて Ubuntu 22.04 の GNU coreutils 8.32 で実際に叩いて確かめたものです。
注目したいのは、下4行に並んだ Access / Modify / Change / Birth という時刻。
ls -l が見せてくれるのは、このうち Modify のひとつだけでした。
4つの時刻を読み分ける
4つの時刻は、それぞれ動く条件が違います。
- Access(atime):中身を最後に読んだ時刻
- Modify(mtime):中身を最後に書き換えた時刻。ls -l に出るのはこれ
- Change(ctime):メタ情報が最後に変わった時刻
- Birth:作成時刻。ファイルシステムが対応していれば表示される
いちばんの落とし穴は、ctime の C が Create ではなく Change を指しているという点。
中身をまったく触らず権限だけ変えても、ctime は動きます。
$ chmod 600 note.txt
$ stat -c 'atime=%x' note.txt
atime=2026-08-08 20:54:24.376031964 +0900
$ stat -c 'mtime=%y' note.txt
mtime=2026-08-08 20:54:25.580031969 +0900
$ stat -c 'ctime=%z' note.txt
ctime=2026-08-08 20:54:26.783031974 +0900
chmod を1回打っただけで Change の秒数だけが進み、Access と Modify は据え置きのままでした。
「中身は変えていないのに更新されている」と見えるときは、たいていメタ情報のほうが動いています。
atime は読むたびには更新されない
読み取りのたびに atime を書き戻すとディスクへの書き込みが増えるため、最近のディストリビューションは relatime という設定でマウントされているのが普通です。
relatime では、atime が mtime より古いときと、前回の更新から1日以上経ったときにしか atime を更新しません。
$ cat note.txt > /dev/null # 1回目
$ stat -c '%x' note.txt
2026-08-08 20:54:39.578032027 +0900
$ cat note.txt > /dev/null # 2回目
$ stat -c '%x' note.txt
2026-08-08 20:54:39.578032027 +0900 # 動かない
読んだのに atime が変わらないのは壊れているからではなく、こういう仕組みだからでした。
-c で欲しい値だけ取り出す
スクリプトに組み込むなら、全項目を表示させる必要はありません。
-c に書式を渡すと、指定した項目だけを1行で返してくれます。
$ stat -c '%s %n' *.txt
12 hard.txt
8 link.txt
12 note.txt
よく使う指定子は、このあたりに絞られます。
- %n:ファイル名/%s:サイズ(バイト)
- %A:権限の記号表記/%a:8進表記
- %U:所有者/%i:inode 番号/%h:ハードリンク数
- %F:種別(regular file・directory・symbolic link)
- %y:mtime/%Y:mtime のエポック秒
なかでも %Y はエポック秒で返るので、シェルの数値比較にそのまま流し込めます。
$ stat -c '%Y %n' note.txt
1786190065 note.txt
リンクの正体を見抜く
stat がとりわけ効いてくるのは、リンクを扱うときでした。
stat は既定でシンボリックリンク自身を見にいき、-L を付けるとリンク先を見にいきます。
$ stat -c '%N %F' link.txt
'link.txt' -> 'note.txt' symbolic link
$ stat -L -c '%N %F' link.txt
'link.txt' regular file
ハードリンクのほうは様子が違い、inode 番号が同じままで Links の数だけが増えるという形で現れます。
$ stat -c '%i %h %n' note.txt hard.txt link.txt
21364 2 note.txt
21364 2 hard.txt
21365 1 link.txt
同じ実体を指す名前が2つある、というハードリンクの性質が、そのまま数字に出ているわけです。
リンクそのものの作り方と使い分けは別の記事にまとめているので、あわせてどうぞ。
出力の Access: (0644/-rw-r–r–) の読み方が怪しいときは、パーミッションの記事から先に目を通すと早いはずです。
最後に
stat は、ls -l では届かない一段深いところを覗くためのコマンドでした。
4つの時刻の意味と -c の書式さえ握っておけば、障害調査でも運用スクリプトでも十分に戦えます。
まずは手元のファイルに stat を1回打ってみるところから、どうぞ。
調べたい対象がシンボリックリンク越しなら、先に絶対パスへ直しておくと迷いません。
以上です。











コメントを残す