Landscape トップページ | < 前の日 2005-07-02 2005-07-06 次の日 2005-07-07 >

Landscape - エンジニアのメモ 2005-07-06

find コマンドの -mtime は +1 でも2日前のファイルが対象


* find コマンドの -mtime は +1 でも2日前のファイルが対象

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [unix] [シェルスクリプト]

find コマンドの -mtime は +1 でも2日前のファイルが対象となる。つまり、(n + 1) 日前のファイルが対象。n は +0 を指定しても、一日以上前のファイルが対象になる。

- find が古いファイルを検索してくれない

とあるテスト用 DB があり、定期的にバックアップを取っている。バックアップ先はディスク容量に余裕がないので、以下のような古くなったバックアップファイルを消す cron を設定しておいたのだが、どうもうまく動いていない模様。今日は7月6日なのに、7月4日のファイルがまだ残っているのだ。

6 0 * * * /usr/bin/find /cygdrive/c/DB_BACKUP -maxdepth 1 -type f -mtime +1 |/usr/bin/xargs /bin/rm -f

毎日午前0時6分に起動。一日以上経過したバックアップファイルを find で探しだし、xargs から起動する rm に渡して削除するというシンプルなコマンド。2003-04-16 の「n 日以前のタイムスタンプを持つファイルを消す」にも書いた。cron と find があるマシンでは重宝している。なんで今になってうまく動かないことが発覚したんだろう? 実行環境が Windows2000 + cygwin だから? まさか。

まずは原因を切り分けよう。xargs に渡す前の find だけを実行してみると、古くなったバックアップファイルが find の対象になっていない。なんでだろう? mtime の指定が間違っているのだろうか? find の man を見てみる。

Manpage of FIND
http://www.linux.or.jp/JM/html/GNU_findutils/man1/find.1.htm ...
-mtime n
ファイルのデータが最後に修正されたのが n*24 時間前なら真。

うーん、間違ってないよね。試しに -mtime +1 を -mtime 1 にしたところ、古いバックアップファイルが find の検索対象となった。ここが間違ってるのかな?

判別式

数値の引き数を

+n
と表わすと n より大きいことを示し、

-n
と表わすと n より小さいことを示す。

n
はちょうど n と等しいことを示す。

別におかしくないよなあ。-mtime +1 なら、24時間以上前なら真ってことでしょ? それとも何か勘違いしてる? ちょっとテストしてみるか。

- テスト

find の削除対象にならないタイムスタンプを持つファイルを作成してみる。

その前に、該当マシンのマシンデイトの確認。
$ date
Wed Jul  6 10:25:14    2005
よし、合ってるね。NTP で合わせてるんだから当たり前だけど。

Windows エクスプローラで確認すると、該当のファイルのタイムスタンプ情報は以下の通り。
作成日時: 2005年7月4日、14:00:16
更新日時: 2005年7月4日、14:00:16
アクセス日時: 2005年7月6日、10:06:52

-mtime は更新日時のことなので、-mtime +1 の「一日以上前のファイル」という 条件には合致するはずだ。

まず touch で当該タイムスタンプを持ったファイルを生成し、ls -l でタイムスタンプを確認。

$ touch -m -t 200507041400.16 200507041400.16

$ ls -l
-rw-r--r--    1 Administ なし            0 Jul  4 14:00 200507041400.16

問題なく生成された。ファイル名も 200507041400.16 にした。

では find 実行。

$ find -mtime 1
./200507041400.16

$ find -mtime +1

あれ? なんで? 明らかに一日以上経過しているファイルなのに、+1 だと find の対象にならず、1 だと find の対象になる。この Windows2000 + cygwin 環境の find がおかしいのか? 念のため TurboLinux Server 6.5 でも同じことをやってみる。

[hiroaki@pro ~/test/find_test]$ find -mtime 1
./200507041400.16

[hiroaki@pro ~/test/find_test]$ find -mtime +1

同じだ・・・。なんでだろう?
+1 の条件を変えて +0 でやってみると検索対象になった。そういうことか。つまり、+0 を指定したら、0 * 24 = 0 なので、全てのファイルが対象になると思うところだが、そうはならないんだろう。

試してみる。touch now で現在時刻の mtime を持つファイルを作成し、mtime +0 で find の検索対象になるか試す。

$ touch now

$ find -mtime +0
./200507041400.16

find の検索対象にならない。そういうことか。

- find の -mtime +n のまとめ

find の -mtime +n の検索対象となるファイルは以下の通り。

mtime +0 今から24時間以上前のファイル
mtime +1 今から48時間以上前のファイル
mtime +2 今から72時間以上前のファイル

(n + 1) * 24 ってことだね。man にそう書いてあれば良かったのに。あとでスクリプトを書いて試してみよう。

- 一時間ずつずらしたタイムスタンプを持つファイル群を生成する Perl One Liner を使ってテスト

以下を実行すると、200個のファイルが生成される。ファイルのタイムスタンプはそれぞれ、一時間前、二時間前、三時間前・・・と200時間前までさかのぼったものを utime 関数を使ってセットする。ファイル名は epoc time そのもの。で、これを find に検索させて、どこが検索対象の境界になるかを調べようと言うわけだ。

$ perl -le 'for (1..200) { $fname = (time - $_ * 3600); open(FH, ">$fname"); print FH ''; close(FH); utime($fname, $fname, $fname); }'

いきなり200個のファイルを作っても結果の検証がしにくくなるだけなので、まずは 35個だけ作ってみる。

$ perl -le 'for (1..35) { $fname = (time - $_ * 3600); open(FH, ">$fname"); print FH ''; close(FH); utime($fname, $fname, $fname); }'

$ ls -ltr
total 35
-rw-r--r--  1 aqua なし 3 Jul  5 12:39 1120534797
-rw-r--r--  1 aqua なし 3 Jul  5 13:39 1120538397
-rw-r--r--  1 aqua なし 3 Jul  5 14:39 1120541997
-rw-r--r--  1 aqua なし 3 Jul  5 15:39 1120545597
-rw-r--r--  1 aqua なし 3 Jul  5 16:39 1120549197
-rw-r--r--  1 aqua なし 3 Jul  5 17:39 1120552797
-rw-r--r--  1 aqua なし 3 Jul  5 18:39 1120556397
-rw-r--r--  1 aqua なし 3 Jul  5 19:39 1120559997
-rw-r--r--  1 aqua なし 3 Jul  5 20:39 1120563597
-rw-r--r--  1 aqua なし 3 Jul  5 21:39 1120567197
-rw-r--r--  1 aqua なし 3 Jul  5 22:39 1120570797
-rw-r--r--  1 aqua なし 3 Jul  5 23:39 1120574397
-rw-r--r--  1 aqua なし 3 Jul  6 00:39 1120577997
-rw-r--r--  1 aqua なし 3 Jul  6 01:39 1120581597
-rw-r--r--  1 aqua なし 3 Jul  6 02:39 1120585197
-rw-r--r--  1 aqua なし 3 Jul  6 03:39 1120588797
-rw-r--r--  1 aqua なし 3 Jul  6 04:39 1120592397
-rw-r--r--  1 aqua なし 3 Jul  6 05:39 1120595997
-rw-r--r--  1 aqua なし 3 Jul  6 06:39 1120599597
-rw-r--r--  1 aqua なし 3 Jul  6 07:39 1120603197
-rw-r--r--  1 aqua なし 3 Jul  6 08:39 1120606797
-rw-r--r--  1 aqua なし 3 Jul  6 09:39 1120610397
-rw-r--r--  1 aqua なし 3 Jul  6 10:39 1120613997
-rw-r--r--  1 aqua なし 3 Jul  6 11:39 1120617597
-rw-r--r--  1 aqua なし 3 Jul  6 12:39 1120621197
-rw-r--r--  1 aqua なし 3 Jul  6 13:39 1120624797
-rw-r--r--  1 aqua なし 2 Jul  6 14:39 1120628397
-rw-r--r--  1 aqua なし 2 Jul  6 15:39 1120631997
-rw-r--r--  1 aqua なし 2 Jul  6 16:39 1120635597
-rw-r--r--  1 aqua なし 2 Jul  6 17:39 1120639197
-rw-r--r--  1 aqua なし 2 Jul  6 18:39 1120642797
-rw-r--r--  1 aqua なし 2 Jul  6 19:39 1120646397
-rw-r--r--  1 aqua なし 2 Jul  6 20:39 1120649997
-rw-r--r--  1 aqua なし 2 Jul  6 21:39 1120653597
-rw-r--r--  1 aqua なし 2 Jul  6 22:39 1120657197

よしできた。ls のオプションに指定した -ltr の意味は、-l がおなじみのパーミッションとタイムスタンプを表示の有効化、-t は「アルファベット順ではなく修正時刻 (inode の `mtime') でのソートの有効化、-r が逆順にするオプション。

ちなみに現在時刻と、実行環境と find のバージョンは以下の通り。
$ date
Wed Jul  6 23:40:41    2005

$ uname -a
CYGWIN_NT-5.1 a64 1.5.17(0.129/4/2) 2005-05-25 19:38 i686 unknown unknown Cygwin

$ find --version
GNU find version 4.2.11-CVS

で、find . -mtime +0 してみる。私の予想通りなら、24時間以上経過しているファイルのみが対象になるはずだ。

$ find . -mtime +0
./1120534797
./1120538397
./1120541997
./1120545597
./1120549197
./1120552797
./1120556397
./1120559997
./1120563597
./1120567197
./1120570797
./1120574397

うーん、これじゃ24時間以上経過したファイルかどうなのかがよくわからないよね。find の出力結果をファイル名じゃなくてタイムスタンプにしてみよう。

$ find . -mtime +0 -printf "%t\n"
Tue Jul  5 12:39:57 2005
Tue Jul  5 13:39:57 2005
Tue Jul  5 14:39:57 2005
Tue Jul  5 15:39:57 2005
Tue Jul  5 16:39:57 2005
Tue Jul  5 17:39:57 2005
Tue Jul  5 18:39:57 2005
Tue Jul  5 19:39:57 2005
Tue Jul  5 20:39:57 2005
Tue Jul  5 21:39:57 2005
Tue Jul  5 22:39:57 2005
Tue Jul  5 23:39:57 2005

うん、"Tue Jul 5 23:39:57 2005" のタイムスタンプを持つファイルは対象になっておらず、確かに現在時刻から24時間以上経過したものだけ対象になってるね。なんでこういう仕様なんだろう? 仕様さえわかればまあいいか。

テストを終えてふと思ったこと。ここまでテストするんだったら find のソースを読んだ方が早い気がする。周りから攻めようとするのはエンジニアらしくないよね。次からはソースを読むようにしよう。

すべての記事の見出し (全1029件)
全カテゴリの一覧と記事の数
カテゴリごとに記事をまとめ読みできます。記事の表題だけを見たい場合は、すべての記事の見出し (カテゴリ別表示) へ。

直近30日分の記事
2007-04-23 (Mon)
2007-03-07 (Wed)
2007-02-27 (Tue)
2007-01-17 (Wed)
2007-01-15 (Mon)
2007-01-14 (Sun)
2007-01-08 (Mon)
2006-12-01 (Fri)
2006-11-22 (Wed)
2006-11-20 (Mon)
2006-11-19 (Sun)
2006-09-30 (Sat)
2006-08-29 (Tue)
2006-08-04 (Fri)
2006-07-27 (Thu)
2006-07-23 (Sun)
2006-07-17 (Mon)
2006-07-10 (Mon)
2006-07-06 (Thu)
2006-07-03 (Mon)
2006-06-29 (Thu)
2006-06-28 (Wed)
2006-06-27 (Tue)
2006-06-25 (Sun)
2006-06-19 (Mon)
2006-06-18 (Sun)
2006-06-15 (Thu)
2006-06-11 (Sun)
2006-06-01 (Thu)
2006-05-30 (Tue)
プロファイル
斎藤 宏明。エンジニアです。宇都宮市に住んでいます。
リンク
RSS
スポンサードリンク
Powered by
さくらインターネット

© 斎藤 宏明 Saito Hiroaki Gmail Address
Landscape - エンジニアのメモ http://sonic64.com/
Landscape はランドスケープと読みます。
ひらがなだと らんどすけーぷ です。