はじめに
前提:CentOS(GNU版のfind)
findで何日前のファイルを探すには mtime,ctime,atime に、分単位であれば mmin,cmin,amin に、「(|+|-) 数値n」をつけて使用する。
どの場面でどのオプションをどのように使えばいいかの判断方法をまとめる。
mtimeとctimeどちらを使うべきか?
結論: mtime
chownやrenameまで考慮に入れたければctimeだが、ファイルのデータのみが判断基準であれば、書き込み時だけ値が変わるmtimeを使う方がいい。cp -pでコピーした時もinodeの関係でctimeは現在時刻が設定されるが、mtimeは変わらない。
他の理由として、mtimeはtouchコマンドで容易に変えられるが、ctimeはfsdbコマンドなどでファイルシステムを直接いじらなければ変えられず、動作確認がし辛い。
touchコマンドでファイルの時間を変えるには以下のようにすればいい。
touch -m -d '20150805 12:28' samplefile #mtimeのみ
touch -a -d '20150805 12:28' samplefile #atimeのみ
touch -d '20150805 12:28' samplefile #mtime,atime両方
ちなみにatimeを使うことは、業務上はあまりないと思う。
mtime,ctime,atimeのわかりやすい解説
UNIXの部屋 コマンド検索: タイムスタンプ
- atime … 最終アクセス時刻 (access time)
- mtime … 最終変更時刻 (modify time)
- ctime … 最終ステータス変更時刻 (change time)
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 が更新される。
time系とmin系どちらを使うべきか?
結論: min
timeは n*24時間
の単位で考えるのに対し、minは n分
の単位で考える。(n|-n|+n)の指定方法からすると、単位は小さい方が指定しやすい。
manの記載に書いてある通り、+ と - はそれぞれ「以上」「以下」ではなく、「より大きい」「未満」となっている。
Numeric arguments can be specified as
+n for greater than n,
-n for less than n,
n for exactly n.
表にすると、
-n | n | +n | |
---|---|---|---|
time | < n*24 | >= n*24, <= (n+1)*24 | > (n+1)*24 |
min | < n | >= n, <= n+1 | > n+1 |
具体的な値に当てはめて考えてみると、timeで +n だと「 n+1 日より前」となるため24時間のずれがあり、minの1分のずれと比べて、直観的でなくわかりづらい。
mtime +2 更新日が3日より前
mmin +2 更新日が3分より前
24時間単位でなくするためには、nに小数を入れると実現できるが、余計わかりづらくなってしまうかもしれないので、minを使う方がいい。
mtime +0.5 更新日が36時間より前
古いファイルを処理するシェルを mtime +1 と書いて実行した場合、「1日と数時間は経っているファイルが処理されていないのはなぜ?」と無駄に考え込んでしまったので、1日を過ぎたファイルを対象にする場合は、mmin +1440と書くようにしている。
参考
http://www.sioazike.info/wordpress/?p=243
from A to Bのように期間を指定するには?
結論: +nと-nを並べて書き、and条件にする
-mmin -2880 -mmin +1440
で「更新日時が2日前~1日前のファイル」となる。
$ date
2015年 8月 7日 金曜日 13:45:32 JST
$ ll
合計 0
-rw-r--r-- 1 root root 0 8月 5 13:00 2015 a
-rw-r--r-- 1 root root 0 8月 6 13:00 2015 b
-rw-r--r-- 1 root root 0 8月 7 13:00 2015 c
# 更新日時が2日前までのファイル(2日前~今)
$ find ./* -mmin -2880
./b
./c
# 更新日時が1日前を過ぎたファイル(∞~1日前)
$ find ./* -mmin +1440
./a
./b
# 更新日時が2日前~1日前のファイル
$ find ./* -mmin -2880 -mmin +1440
./b
-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)になる。
$ date
2015年 8月 7日 金曜日 14:08:37 JST
$ ll
合計 0
-rw-r--r-- 1 root root 0 8月 7 13:00 2015 c
$ find ./* -mmin +120
$ find ./* -daystart -mmin +120
./c
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
では検索にヒットしない。
echo -n 'NOW: ' && date "+%Y%m%d %H:%M"
touch -m -d '20161229 12:28' dumpfile_20161229
echo -n 'without -daystart: ' && find . -mtime +2 -name dumpfile_20161229
echo
echo -n 'with -daystart: ' && find . -daystart -mtime +2 -name dumpfile_20161229
実行結果
NOW: 20170101 11:35
without -daystart:
with -daystart: ./dumpfile_20161229
上記スクリプトでは、現在時刻(つまり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_