findで時間を指定する~mtime,ctime,atimeとmmin,cmin,amin

2017/01/01

前提:CentOS(GNU版のfind)

findで何日前のファイルを探すには mtime,ctime,atime に、分単位であれば mmin,cmin,amin に、「(|+|-) 数値n」をつけて使用する。
どの場面でどのオプションをどのように使えばいいかの判断方法をまとめる。

目次

---------------------------------------------------------------------
1)mtimeとctimeどちらを使うべきか?
2)time系とmin系どちらを使うべきか?
3)from A to Bのように期間を指定するには?
4)-daystartオプションの考え方は?
---------------------------------------------------------------------

1)mtimeとctimeどちらを使うべきか?

mtime
chownやrenameまで考慮に入れたければctimeだが、ファイルのデータのみが判断基準であれば、書き込み時だけ値が変わるmtimeを使う方がいい。cp -pでコピーした時もinodeの関係でctimeは現在時刻が設定されるが、mtimeは変わらない。

他の理由として、mtimeはtouchコマンドで容易に変えられるが、ctimeはfsdbコマンドなどでファイルシステムを直接いじらなければ変えられず、動作確認がし辛いから。
※touchコマンドでファイルの時間を変える例

ちなみにatimeを使うことは、業務上はあまりないと思う。

mtime,ctime,atimeのわかりやすい解説
UNIXの部屋 コマンド検索: タイムスタンプ

  • atime … 最終アクセス時刻 (access time)
  • mtime … 最終変更時刻 (modify time)
  • ctime … 最終ステータス変更時刻 (change time)
atime・mtime・ctime
atime は、最後にファイルにアクセスした時刻のこと。より正確には、ファイル内容を read(2) した場合に変更される。ファイルをオープンしただけでは変更されないし、ファイル内容を write(2) しても変更されない。当然ながら、read(2) する権限がなかった場合も変更されない。

mtime は、最後にファイルを変更した時刻のこと。より正確には、ファイルに write(2) または truncate(2) した場合に変更される。

ctime は、最後にファイルを変更した時刻のこと。より正確には、ファイルに write(2) または truncate(2) した場合、そして inode データの修正を行った場合に変更される。inode データに含まれるのは、

  • ファイル名
  • ファイルサイズ
  • パーミッション
  • リンク数
  • オーナー・グループ

などである。つまり、write(2)・rename(2)・truncate(2)・chmod(2)・link(2)・chown(2) などのシステムコールを発行すると ctime が更新される。

2)time系とmin系どちらを使うべきか?

min
timeは n*24時間 の単位で考えるのに対し、minは n分 の単位で考える。(n|-n|+n)の指定方法からすると、単位は小さい方が指定しやすい。
manの記載に書いてある通り、+ と - はそれぞれ「以上」「以下」ではなく、「より大きい」「未満」となっている。

表にすると、

-n n +n
time < n*24 >= n*24, <= (n+1)*24 > (n+1)*24
min < n >= n, <= n+1 > n+1

具体的な値に当てはめて考えてみると、+n と日本語でかいた n+1日より前 の表記が1つずれているため、timeだと24時間のずれがあり、minの1分のずれと比べて、直観的でなくわかりづらい。

24時間単位でなくするためには、nに小数を入れると実現できるが、余計わかりづらくなってしまうかもしれないので、minを使う方がいい。

古いファイルを処理するシェルを mtime +1 と書いて実行した場合、「1日と数時間は経っているファイルが処理されていないのはなぜ?」と無駄に考え込んでしまったので、1日を過ぎたファイルを対象にする場合は、mmin +1440と書くようにしている。

参考
http://www.sioazike.info/wordpress/?p=243

3)from A to Bのように期間を指定するには?

+nと-nを並べて書き、and条件にする
「-mmin -2880 -mmin +1440」で「更新日時が2日前~1日前のファイル」となる。

4)-daystartオプションの考え方は?

http://linuxjm.osdn.jp/html/GNU_findutils/man1/find.1.html

-daystart
-amin, -atime, -cmin, -ctime, -mmin, -mtime において、今日 (すなわち 0 日前) の始まりを今現在から 24 時間前ではなく、コマンド実行当日の 0 時にする。このオプションが影響を及ぼすのは、コマンドラインで自分より後に指定された判別式だけである。

[訳注]:
-amin, -cmin, -mmin のことも考慮に入れると、次のように言えばよいのかもしれない。デフォルトでは時間を計算するときの基準を今現在に置くが、-daystart を指定すると、時間計算の基準が今日の 24:00 になる。

引用の訳注がわかりやすい。
-daystartを指定すると、計算基準が今日の 24:00 (= 明日の 0:00)になる。

2時間以上前の更新ファイルを検索するときに、-daystartがついていないと、現在時刻の2時間前が計算されるので、当然1時間前の更新ファイルは検索されないが、-daystartをつけると、今日の 24:00 から2時間前が計算されるので(つまり22:00)、13:00のファイルが検索される。

-daystartの使いどころは、DBのdumpをcronで削除、作成している場合などで、削除対象検索に便利。
mysqldumpのような実行に長時間かかり、かつ何分で終わるか定かでないコマンドの場合、生成されたファイルの更新日時がどうなるかは不明である。mysqldumpで最新3日分のバックアップを保持するという要件を考えてみる。cronで古いdumpファイルを削除し、その後新しいdumpファイルを作成するというスクリプトを実行する場合、3日前のデータを削除対象としてファイルを探すのに-mtime +2では検索にヒットしない。

実行結果

上記スクリプトでは、現在時刻(つまりcron実行開始日時を想定)が11:35なのに対してファイルのmtimeが12:28となっている。これはdump作成に1時間程度時間がかかったからという想定をしているから。
ここで-mtime +2しても実際には丸3日間前のファイルではなく、2日+23時間程度前のファイルなので検索にヒットしない。-daystartオプションを付けることで、findの実行時間が01/01の11:35ではなく01/01の24:00となるので、12/29の12:28のファイルは丸3日以上前のファイルとなり、検索にヒットする。

参考
http://doruby.kbmj.com/SK/20090731/find_mtime_

findの日付、時間検索系関連ページ

findで具体的な日付、時間で検索するnewerXYオプション

-Linux
-