statコマンドとは、ファイルのサイズ・権限・所有者・inode番号・4種類のタイムスタンプ(atime・mtime・ctime・Birth)をまとめて表示するコマンドです。 ls -l が見せるのは主に更新日時(mtime)1つですが、stat なら「最後に読まれた時刻」「権限が変わった時刻」「作られた時刻」までナノ秒単位で確認できます。

この記事では、cat・追記・chmod・chown・mv・cp・touch・ln などの操作ごとにどのタイムスタンプが変わるかを実際に測った一覧表、stat -c の書式指定子の全一覧とコピペ用ワンライナー、relatime で atime が動かない理由、macOS(BSD)版 stat との対応、file・ls -l との使い分けをまとめます。実行結果はすべて Ubuntu 24.04 / GNU coreutils 9.4 / ext4(relatime)/ カーネル 6.18 で root ユーザーとして動かしたものです。macOS 側は今回動かしていないため「未実行」と明記しています。

statとタイムスタンプの早見表

4つのタイムスタンプ

表示名 呼び名 意味 書式指定子(読みやすい形/エポック秒) ls での表示
Access atime 中身を最後に読んだ時刻 %x / %X ls -lu
Modify mtime 中身を最後に書き換えた時刻 %y / %Y ls -l(既定)
Change ctime inode の情報(権限・所有者・名前・リンク数・サイズ)が最後に変わった時刻 %z / %Z ls -lc
Birth btime(crtime) ファイルが作られた時刻 %w / %W ls -l --time=birth

ctime は「作成(create)」ではなく「変更(change)」の c です。 作成時刻は Birth です。

操作ごとに変わるタイムスタンプ(実測)

「変」は時刻が更新されたもの、「―」は変わらなかったものです。

操作 atime mtime ctime Birth 補足
cat f.txt(書き込み直後の1回目) 変 ― ― ― relatime の条件に当てはまるため更新
cat f.txt(2回目) ― ― ― ― relatime では毎回は更新しない
ls -l f.txt、stat f.txt ― ― ― ― 情報を見るだけでは何も変わらない
echo two >> f.txt(追記) ― 変 変 ― 中身が変わるとサイズも変わるため ctime も動く
echo new > f.txt(上書き) ― 変 変 ― 同じ inode のまま中身を入れ替える
truncate -s 0 f.txt ― 変 変 ―
chmod 600 f.txt ― ― 変 ― 権限は inode の情報
chown nobody f.txt ― ― 変 ― 所有者も inode の情報
mv f.txt g.txt(同じファイルシステム内) ― ― 変 ― 改名でも中身は触らない
ln f.txt hard.txt(ハードリンク作成) ― ― 変 ― リンク数が増える
rm hard.txt(ハードリンクを1つ削除) ― ― 変 ― リンク数が減る
ln -s f.txt sym.txt(リンク先の f.txt 側) ― ― ― ― シンボリックリンクは別の inode
touch f.txt 変 変 変 ―
touch -a f.txt 変 ― 変 ― atime だけ指定しても ctime は動く
touch -m f.txt ― 変 変 ―
touch -d "2020-01-01 00:00" f.txt 変 変 変 ― 過去の日付にできるのは atime と mtime。ctime は現在時刻になる
cp f.txt c.txt(既存のコピー先 c.txt) ― 変 変 ― コピー先は上書きされる
cp -p f.txt c.txt(既存のコピー先 c.txt) 変 変 変 ― atime・mtime がコピー元と同じ値になる
sed -i で置き換え保存 変 変 変 変 新しいファイルを作って入れ替えるため inode 番号も変わる
gzip してから gunzip ― ― 変 変 作り直されるが、mtime は元の値が復元される

覚え方は「中身を書いたら mtime と ctime、属性だけなら ctime、読んだら atime(ただし条件つき)」です。 ctime は touch でも過去の値に設定できないため、「最近なにか手が入ったか」を確かめる手がかりになります。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Linux statコマンドの使い方|atime・mtime・ctime早見表」

statの基本的な使い方と出力の読み方

stat memo.txt

実行結果:

  File: memo.txt
  Size: 6           Blocks: 8          IO Block: 4096   regular file
Device: 254,0   Inode: 3211666     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2026-10-03 14:27:45.998729750 +0900
Modify: 2026-10-03 14:27:46.003304640 +0900
Change: 2026-10-03 14:27:46.005260727 +0900
 Birth: 2026-10-03 14:27:45.998729750 +0900
項目 この例の値 意味
File memo.txt ファイル名。シンボリックリンクなら「名前 -> リンク先」
Size 6 バイト数
Blocks 8 割り当てられたブロック数(1ブロック 512 バイト単位。%B で確認できる)
IO Block 4096 入出力に適したブロックサイズ
種類 regular file 通常ファイル。ほかに directory、symbolic link、fifo、socket、character special file など
Device 254,0 ファイルがあるデバイスの番号(メジャー,マイナー)
Inode 3211666 inode 番号。同じファイルシステム内で同じ番号なら同じ実体
Links 1 ハードリンクの数
Access(1つ目) 0644/-rw-r--r-- 権限。8進表記と記号表記
Uid / Gid 0/root 所有者とグループ(番号/名前)
Access(2つ目)/Modify/Change/Birth 時刻 atime/mtime/ctime/作成時刻

「Access」が2回出てきますが、1つ目は権限(アクセス権)、2つ目は最終アクセス時刻です。

よく使うオプション

オプション 働き 例
(なし) 上のような詳細表示 stat memo.txt
-c 書式、--format=書式 必要な項目だけを表示(末尾に改行が付く) stat -c '%a %n' memo.txt
--printf=書式 -c と同じだが改行を付けない。\n や \t が使える stat --printf '%n\t%s\n' memo.txt
-L、--dereference シンボリックリンクをたどり、リンク先の情報を表示 stat -L link.txt
-f、--file-system ファイルではなく、そのファイルが載っているファイルシステムの情報 stat -f .
-t、--terse 1行にまとめた機械処理向けの表示 stat -t memo.txt

シンボリックリンクに対しては、既定ではリンクそのものの情報が出ます。

$ stat link.txt
  File: link.txt -> memo.txt
  Size: 8           Blocks: 0          IO Block: 4096   symbolic link
Device: 254,0   Inode: 3211668     Links: 1

$ stat -L link.txt
  File: link.txt
  Size: 6           Blocks: 8          IO Block: 4096   regular file
Device: 254,0   Inode: 3211666     Links: 1

(それぞれ先頭3行を抜粋)-L を付けると Size が 8(リンク先の名前 memo.txt の文字数)から 6(中身のバイト数)に変わり、Inode も memo.txt と同じ番号になります。

stat -f でファイルシステムの情報を見る

$ stat -f .
  File: "."
    ID: 55d9f9279eba0be0 Namelen: 255     Type: ext2/ext3
Block size: 4096       Fundamental block size: 4096
Blocks: Total: 66053021   Free: 56375732   Available: 1285236
Inodes: Total: 16777216   Free: 15993961

$ stat -f -c '%T  ブロック=%S  空き=%a/%b' .
ext2/ext3  ブロック=4096  空き=1285236/66053021

ext4 でも Type は「ext2/ext3」と表示されます(3つは同じ識別番号を共有しているためです)。ファイル名の最大長(Namelen)や inode の残り数をスクリプトで取りたいときに便利です。

存在しないファイルを指定したとき

$ stat nothing.txt
stat: cannot statx 'nothing.txt': No such file or directory
$ echo $?
1

終了コードが 1 になるので、スクリプトでは存在確認を兼ねて使えます。

stat -c の書式指定子 全一覧

GNU coreutils 9.4 の stat --help に載っている指定子を、memo.txt での実際の出力と合わせて整理しました。

ファイル用

指定子 意味 memo.txt での出力
%n ファイル名 memo.txt
%N 引用符つきのファイル名。リンクならリンク先も表示 'memo.txt'(link.txt では 'link.txt' -> 'memo.txt')
%s サイズ(バイト) 6
%b 割り当てブロック数 8
%B %b の1ブロックあたりのバイト数 512
%o 入出力に適した転送サイズ 4096
%a 権限(8進) 644
%A 権限と種類(記号) -rw-r--r--
%f モードの生の値(16進) 81a4
%F ファイルの種類 regular file
%u 所有者のユーザーID 0
%U 所有者のユーザー名 root
%g グループID 0
%G グループ名 root
%i inode 番号 3211666
%h ハードリンク数 1
%m マウントポイント /
%d デバイス番号(10進) 65024
%D デバイス番号(16進) fe00
%Hd デバイスのメジャー番号 254
%Ld デバイスのマイナー番号 0
%r デバイス種別(10進、デバイスファイル用) 0
%R デバイス種別(16進、デバイスファイル用) 0
%Hr デバイス種別のメジャー番号(10進) 0
%Lr デバイス種別のマイナー番号(10進) 0
%t デバイス種別のメジャー番号(16進) 0
%T デバイス種別のマイナー番号(16進) 0
%C SELinux のセキュリティコンテキスト ?(SELinux 無効の環境のため取得できず)
%x atime(読みやすい形) 2026-10-03 14:27:45.998729750 +0900
%X atime(エポック秒) 1791005265
%y mtime(読みやすい形) 2026-10-03 14:27:46.003304640 +0900
%Y mtime(エポック秒) 1791005266
%z ctime(読みやすい形) 2026-10-03 14:27:46.005260727 +0900
%Z ctime(エポック秒) 1791005266
%w 作成時刻(読みやすい形)。不明なら - 2026-10-03 14:27:45.998729750 +0900
%W 作成時刻(エポック秒)。不明なら 0 1791005265

時刻の指定子は「小文字が読みやすい形、大文字がエポック秒」と覚えると迷いません(x/X、y/Y、z/Z、w/W)。

ファイルシステム用(-f と組み合わせる)

指定子 意味
%n ファイル名
%T ファイルシステムの種類(読みやすい形)
%t ファイルシステムの種類(16進)
%i ファイルシステムID(16進)
%l ファイル名の最大長
%s ブロックサイズ(転送向け)
%S 基本ブロックサイズ(ブロック数の計算用)
%b 全データブロック数
%f 空きブロック数
%a 一般ユーザーが使える空きブロック数
%c inode の総数
%d 空き inode 数

同じ文字でも、-f の有無で意味が変わります(%a はファイル用では権限、ファイルシステム用では空きブロック数)。

コピペ用ワンライナー集

すべて実行して出力を確認しています。

やりたいこと コマンド 出力例
更新日時だけ取る stat -c '%y' memo.txt 2026-10-03 14:27:46.003304640 +0900
更新日時を秒まで(小数点以下を落とす) stat -c '%y' memo.txt | cut -d. -f1 2026-10-03 14:27:46
更新日時をエポック秒で取る stat -c '%Y' memo.txt 1791005266
更新日時を好きな形式で date -r memo.txt '+%Y%m%d_%H%M%S' 20261003_142746
エポック秒を日時に戻す date -d "@$(stat -c %Y memo.txt)" '+%Y-%m-%d %H:%M:%S' 2026-10-03 14:27:46
権限を8進で取る stat -c '%a' memo.txt 644
権限を8進とファイル名で並べる stat -c '%a %n' memo.txt 644 memo.txt
権限を記号で取る stat -c '%A' memo.txt -rw-r--r--
サイズ(バイト)だけ取る stat -c '%s' memo.txt 6
所有者:グループ stat -c '%U:%G' memo.txt root:root
inode 番号 stat -c '%i' memo.txt 3211666
ハードリンク数 stat -c '%h' memo.txt 1
ファイルの種類 stat -c '%F' memo.txt regular file
リンク先を表示 stat -c '%N' link.txt 'link.txt' -> 'memo.txt'
作成時刻 stat -c '%w' memo.txt 2026-10-03 14:27:45.998729750 +0900
タブ区切りで名前とサイズ stat --printf '%n\t%s\n' memo.txt run.sh memo.txt(タブ)6、run.sh(タブ)20 の2行
ファイルシステムの種類 stat -f -c '%T' . ext2/ext3

スクリプトでの使用例

# 権限が 755 かどうか確かめる
[ "$(stat -c %a run.sh)" = 755 ] && echo "run.sh is 755"

# 最後の更新から何秒たったか
echo $(( $(date +%s) - $(stat -c %Y memo.txt) )) sec

# カレントディレクトリのファイルを「権限 所有者 サイズ 名前」で一覧
stat -c '%a %U %s %n' *

# 更新が新しい順に下から3件(エポック秒で並べ替え)
stat -c '%Y %n' * | sort -n | tail -3

実行結果(1つ目、2つ目、3つ目の一部):

run.sh is 755
0 sec
644 root 8 conf.json
644 root 256 data.bin
644 root 0 empty
777 root 8 link.txt
755 root 4096 logs
644 root 6 memo.txt
755 root 20 run.sh

シンボリックリンク(link.txt)の権限は 777 と表示されます。リンク自体の権限は使われず、実際にはリンク先の権限で判定されます。

atime・mtime・ctime・Birth の違いを確かめる

早見表の結果は、次のスクリプトで「操作の前後で stat の値を比べる」方法で測りました。手元の環境で確かめたいときにそのまま使えます。

#!/bin/bash
snap(){ stat -c '%x|%y|%z|%w|%i' "$1"; }
cmp(){ local label="$1" b="$2" a="$3" r=""
  IFS='|' read -r ba bm bc bb bi <<<"$b"; IFS='|' read -r aa am ac ab ai <<<"$a"
  [ "$ba" != "$aa" ] && r="$r atime"; [ "$bm" != "$am" ] && r="$r mtime"
  [ "$bc" != "$ac" ] && r="$r ctime"; [ "$bb" != "$ab" ] && r="$r Birth"
  [ "$bi" != "$ai" ] && r="$r (inode変化)"
  printf '%-40s | %s\n' "$label" "${r:- なし}"; }
# op ラベル 操作前に見るファイル 操作後に見るファイル コマンド
op(){ local b a; b=$(snap "$2"); sleep 0.05; eval "$4" >/dev/null 2>&1; sleep 0.02; a=$(snap "$3"); cmp "$1" "$b" "$a"; }

echo one > f.txt; sleep 0.05
op "cat f.txt (1回目)" f.txt f.txt 'cat f.txt'
op "cat f.txt (2回目)" f.txt f.txt 'cat f.txt'
op "echo two >> f.txt" f.txt f.txt 'echo two >> f.txt'
op "chmod 600 f.txt"   f.txt f.txt 'chmod 600 f.txt'
op "mv f.txt g.txt"    f.txt g.txt 'mv f.txt g.txt'

実行結果:

cat f.txt (1回目)                        |  atime
cat f.txt (2回目)                        |  なし
echo two >> f.txt                        |  mtime ctime
chmod 600 f.txt                          |  ctime
mv f.txt g.txt                           |  ctime

cp と mv で日時がどうなるか

コピーでは、新しくできたファイルの mtime は「コピーした時刻」になります。元の日時を引き継ぎたいときは cp -p を使います。

touch -d "2020-01-01 00:00" f.txt
cp f.txt n.txt
cp -p f.txt p.txt
stat -c '%n  mtime=%y  birth=%w' f.txt n.txt p.txt
f.txt  mtime=2020-01-01 00:00:00.000000000 +0900  birth=2026-10-03 14:27:24.690728484 +0900
n.txt  mtime=2026-10-03 14:27:24.791428691 +0900  birth=2026-10-03 14:27:24.786728489 +0900
p.txt  mtime=2020-01-01 00:00:00.000000000 +0900  birth=2026-10-03 14:27:24.791428691 +0900
操作 できたファイルの mtime できたファイルの Birth
cp f.txt n.txt コピーした時刻 コピーした時刻
cp -p f.txt p.txt コピー元と同じ コピーした時刻
mv f.txt g.txt(同じファイルシステム内) 変わらない 変わらない(inode がそのまま)

mtime は引き継げても、Birth は引き継げません。 Birth はそのファイルシステム上で inode が作られた時刻だからです。別のファイルシステムへの mv は「コピーして元を消す」動きになるため、Birth は新しくなります(この点は今回は測っていません)。

ディレクトリのタイムスタンプ

ディレクトリの mtime は「中の名前の一覧」が変わったときに動きます。

操作 ディレクトリ d の atime mtime ctime
d の中にファイルを新規作成(touch d/a) ― 変 変
d の中のファイルに追記(echo x >> d/a) ― ― ―
d の中で改名(mv d/a d/b) ― 変 変
d の中のファイルを削除(rm d/b) ― 変 変
ls d(1回目) 変 ― ―
ls d(2回目) ― ― ―

中のファイルを編集しても、ディレクトリの mtime は変わりません。 「フォルダの更新日時は以前のままなのに、中のファイルは新しい」という状態は正常です。

relatime・noatimeでatimeが動かない理由

「cat したのに atime が変わらない」のは、マウントオプション relatime の働きです。読むたびに atime を書き込むとディスクへの書き込みが増えるため、Linux では relatime が既定になっています。

relatime では、次のどちらかに当てはまるときだけ atime を更新します。

条件 今回の実測
現在の atime が mtime または ctime より前(=最後に読んだあとで変更があった) 書き込み直後の1回目の cat で atime が更新された
現在の atime が24時間より前 atime を2日前にしてから cat すると更新された
上のどちらでもない 2回目の cat では変わらなかった

24時間の条件は次のように確かめました。

echo x > r.txt; cat r.txt > /dev/null
touch -a -d "2 days ago" r.txt     # atime だけを2日前にする
cat r.txt > /dev/null              # → atime が更新された
cat r.txt > /dev/null              # → 変わらなかった

マウントオプションごとの違いは、小さな tmpfs を3種類のオプションでマウントして確かめました(同じファイルを続けて読み、3回目の cat の前後を比較)。

mkdir m_noatime
mount -t tmpfs -o noatime,size=1m tmpfs m_noatime
マウントオプション 3回目の cat で atime が変わったか 動き
relatime(既定) 変わらない 条件に当てはまるときだけ更新
noatime 変わらない 読んでも更新しない
strictatime 変わった 読むたびに更新

いま使っているファイルシステムのオプションは、次のコマンドで確認できます。

$ findmnt -T . -o TARGET,FSTYPE,OPTIONS
TARGET FSTYPE OPTIONS
/      ext4   rw,relatime,discard,resv_strict,resuid=65534,resgid=65534
目的 見るタイムスタンプ 注意
最後に中身が変わった時刻 mtime cp -p や touch -d で任意の値にできる
最後に何らかの変更があった時刻 ctime 利用者が任意の値に設定する手段が無い
最近読まれたかどうかの目安 atime relatime では「1日単位の目安」と考える。noatime では使えない
作られた時刻 Birth ファイルシステムの対応が必要

Birth(作成時刻)が「-」になる場合

Birth は、ファイルシステムが作成時刻を記録していて、かつ stat がそれを取得できる場合に表示されます。今回の環境では ext4 と tmpfs で表示され、/proc 配下のファイルでは「-」でした。

$ stat -c '%w' /dev/shm /proc/version
2026-10-03 14:16:48.598690672 +0900
-

「-」と表示される場合は、そのファイルシステムが作成時刻を持っていないか、以前のバージョンの環境で取得に対応していないかのどちらかです。作成時刻が必要な処理では、%W が 0 でないことを確かめてから使うと安心です。

inode番号で同じ実体かを確かめる、日時でファイルを探す

ハードリンクとコピーを見分ける

inode 番号(%i)とリンク数(%h)を並べると、同じ実体かどうかが一目でわかります。 a.txt にハードリンク b.txt、コピー c.txt、シンボリックリンク s.txt を作って比べました。

echo data > a.txt
ln a.txt b.txt        # ハードリンク
cp a.txt c.txt        # コピー
ln -s a.txt s.txt     # シンボリックリンク
stat -c '%i %h %n' a.txt b.txt c.txt s.txt
1393093 2 a.txt
1393093 2 b.txt
1394104 1 c.txt
1394116 1 s.txt
ファイル inode 番号 リンク数 読み取れること
a.txt と b.txt 同じ 2 名前が2つある同じ実体。片方を書き換えるともう片方も変わる
c.txt 別 1 中身が同じだけの別のファイル
s.txt 別 1 a.txt という名前を指す小さな別ファイル

シェルの条件式では -ef で同じ判定ができます。

[ a.txt -ef b.txt ] && echo "a.txt と b.txt は同じ実体"
[ a.txt -ef c.txt ] || echo "a.txt と c.txt は別の実体"
a.txt と b.txt は同じ実体
a.txt と c.txt は別の実体

タイムスタンプを条件にファイルを探す

stat は「1つのファイルの日時を見る」コマンドです。「日時を条件に探す」ときは find を組み合わせます。3日前の日時にした old.log と、作ったばかりの new.log で確かめました。

やりたいこと コマンド 実行結果
24時間以内に更新されたファイル find . -mtime -1 -name '*.log' ./new.log
更新から2日以上たったファイル find . -mtime +1 -name '*.log' ./old.log
基準のファイルより後に更新されたファイル find . -newer old.log -type f ./new.log など4件
更新日つきで一覧 find . -name '*.log' -printf '%TY-%Tm-%Td %p\n' 日付とパスの2行

-mtime を -atime や -ctime に替えると、それぞれのタイムスタンプで探せます。atime を条件にする場合は、前の章のとおり relatime の環境では1日単位の目安になる点を考慮します。

GNU statとmacOS(BSD)statの対応表

macOS の stat は BSD 系で、オプションの意味が GNU 版と異なります。特に -f は、GNU では「ファイルシステム情報」、BSD では「書式指定」と、まったく別の働きです。

以下の macOS 側は今回の環境では未実行で、一般に知られている BSD stat の仕様に基づく対応です。利用前に手元の man stat で確かめてください。

やりたいこと Linux(GNU stat・実行して確認) macOS(BSD stat・未実行)
書式を指定する stat -c '書式' ファイル stat -f '書式' ファイル
更新日時(エポック秒) stat -c '%Y' stat -f '%m'
更新日時(読みやすい形) stat -c '%y' stat -f '%Sm'
日時の表示形式を指定 date -r ファイル '+%Y-%m-%d' stat -f '%Sm' -t '%Y-%m-%d'
アクセス日時(エポック秒) stat -c '%X' stat -f '%a'
状態変更日時(エポック秒) stat -c '%Z' stat -f '%c'
作成日時(エポック秒) stat -c '%W' stat -f '%B'
権限(8進) stat -c '%a' stat -f '%Lp'
権限(記号) stat -c '%A' stat -f '%Sp'
サイズ(バイト) stat -c '%s' stat -f '%z'
所有者名 stat -c '%U' stat -f '%Su'
グループ名 stat -c '%G' stat -f '%Sg'
inode 番号 stat -c '%i' stat -f '%i'
ハードリンク数 stat -c '%h' stat -f '%l'
ファイル名 stat -c '%n' stat -f '%N'
リンクをたどる stat -L stat -L
Linux 風の詳細表示 stat(既定) stat -x
ファイルシステム情報 stat -f (stat には無い。df などを使う)

両方で動かすスクリプトでは、次のように切り替える方法があります(Linux 側の分岐のみ実行して確認)。

mtime_epoch() {
  if stat -c '%Y' "$1" >/dev/null 2>&1; then
    stat -c '%Y' "$1"      # GNU
  else
    stat -f '%m' "$1"      # BSD
  fi
}
mtime_epoch memo.txt

ファイルの種類を確認する:stat・file・ls -l の使い分け

「このファイルは何か」を知りたいとき、3つのコマンドは見ているものが違います。

コマンド 見ているもの わかること 向いている場面
ls -l inode の種類(先頭1文字) 通常ファイル・ディレクトリ・リンクなどの区別 一覧でざっと確認
stat -c '%F' inode の種類(言葉で) 同上を文字列で スクリプトで種類を判定
file ファイルの中身 テキストか、画像か、圧縮ファイルか、実行ファイルか 拡張子が無い・信用できないファイルの確認

ls -l の先頭1文字と stat %F の対応

$ ls -l
-rw-r--r-- 1 root root    6 Oct  3 14:27 memo.txt
drwxr-xr-x 2 root root 4096 Oct  3 14:27 logs
lrwxrwxrwx 1 root root    8 Oct  3 14:27 link.txt -> memo.txt
prw-r--r-- 1 root root    0 Oct  3 14:27 pipe
-rwxr-xr-x 1 root root   20 Oct  3 14:27 run.sh
$ ls -ld /dev/null
crw-rw-rw- 1 root root 1, 3 Oct  3 06:55 /dev/null

(ls -l の出力は該当行を抜粋)

ls -l の先頭 stat -c '%F' の出力 種類 今回の確認
- regular file 通常ファイル 実行して確認
d directory ディレクトリ 実行して確認
l symbolic link シンボリックリンク 実行して確認
p fifo 名前付きパイプ 実行して確認
c character special file キャラクタデバイス 実行して確認(/dev/null)
s socket ソケット 実行して確認(%F のみ)
b block special file ブロックデバイス 未実行(この環境に該当ファイルが無い)

file コマンドで中身から判定する

file は拡張子ではなく、中身の先頭部分などから種類を推定します(file 5.45 で実行)。

$ file *
conf.json:    JSON text data
empty:        empty
items.csv:    CSV ASCII text
items.csv.gz: gzip compressed data, was "items.csv", last modified: Sat Oct  3 05:27:46 2026, from Unix, original size modulo 2^32 14
link.txt:     symbolic link to memo.txt
logs:         directory
memo.txt:     ASCII text
photo.dat:    PNG image data, 16 x 16, 8-bit/color RGB, non-interlaced
pipe:         fifo (named pipe)
run.sh:       Bourne-Again shell script, ASCII text executable

photo.dat は拡張子が .dat ですが、中身から PNG 画像と判定されています。

やりたいこと コマンド 出力
種類だけ表示(ファイル名を省く) file -b memo.txt ASCII text
MIME タイプと文字コード file -i memo.txt memo.txt: text/plain; charset=us-ascii
MIME タイプだけ file --mime-type -b photo.dat image/png
リンク先の中身を判定 file -L link.txt link.txt: ASCII text

file の判定は推定です。規則性のないバイナリデータ(0〜255 を順に並べた 256 バイトのファイル)を渡したところ「Targa image data ...」と表示されました。結果は手がかりとして使い、重要な判定では中身を別の方法でも確かめるのが安全です。

よくある質問

Q. ctime を過去の日時に変更できますか? A. touch では変更できません。今回の測定でも、touch -d で atime と mtime を 2020 年にしたとき、ctime は実行した時刻になりました。ctime はカーネルが inode を更新したときに自動で記録する値です。

Q. ls -l の日時と stat のどれが同じですか? A. ls -l が既定で表示するのは mtime(Modify)です。ls -lu で atime、ls -lc で ctime、ls -l --time=birth で作成時刻を表示できます。秒より細かい値まで見たいときは stat を使います。

Q. ファイルを編集していないのに ctime だけ新しいのはなぜですか? A. 権限の変更(chmod)、所有者の変更(chown)、改名や移動(mv)、ハードリンクの作成や削除で ctime だけが動きます。早見表のとおり、これらの操作では mtime は変わりません。

Q. エディタで保存したら inode 番号が変わりました。 A. 「新しいファイルに書いてから元の名前に入れ替える」方式で保存するツールでは、inode が新しくなります。今回の sed -i でも inode 番号と Birth が変わりました。ハードリンクを張っているファイルでは、リンクが別々の実体になる点に気をつけます。

まとめ

  • stat は4つのタイムスタンプ(atime・mtime・ctime・Birth)と権限・所有者・inode をまとめて表示する
  • 中身を書いたら mtime と ctime、属性だけなら ctime、読んだら atime(条件つき)が動く
  • ctime は change(変更)であって作成ではない。作成時刻は Birth(%w)
  • 必要な項目だけ取るなら stat -c。更新日時は %y/%Y、8進の権限は %a、サイズは %s
  • atime が動かないのは relatime の働き。atime が mtime・ctime より前のとき、または24時間より前のときだけ更新される
  • macOS の stat は -f が書式指定。GNU の -c に相当し、指定子も異なる(未実行・要確認)
  • 種類の確認は、inode の種類なら ls -l と stat %F、中身の種類なら file

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Linux statコマンドの使い方|atime・mtime・ctime早見表」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?