-mminはあっても-msecはないのか!
findコマンドは、様々な条件でファイル抽出ができて便利。でも時間の新旧で絞り込む機能は弱いと言わざるを得ない。
通常のタイムスタンプ(m:ファイルの中身を修正した日時)において、POSIXで規定されているのは-mtime
だけであり、しかも後ろには単純な数字しか指定できない。つまり現在から1日(=86400秒)単位での新旧比較しかできない。
- 指定した年月日時分秒より新しい、より古い、等しい
- n秒前より新しい、より古い、等しい
なんて比較はしたくてもできなかった。独自のオプションも使えばある程度できるけどOSによって使えたり使えなかったりするし……。さてどうしよう。
-newerオプションを活用するのが鍵
しかし-newer
というオプションを使うと辛うじてこの悩みを解決できる。これは-newerの後ろで指定したファイルをとタイムスタンプ比較を行い、それよりも新しければ真とするという働きを持つオプションだ。
1.指定日時との比較
これを使えばまず、指定日時との比較は簡単にできる。
YYYY/MM/DD hhssよりも新しいファイルを抽出したいなら、こんなシェルスクリプトを書けばよい。
touch -t YYYYMMDDhhmm.ss thattime.tmp
find /TARGET/DIR -newer thattime.tmp
rm thattime.tmp
touchコマンドの書式の事情により、mmとssの間にピリオドを挿れないといけない点に注意してもらいたい。
次に「より古い」ものを抽出したいならどうするか。それには基準となる日時の1秒前(YYYYMMDDhhmms1
とする)のタイムスタンプを持つファイルを作り、-newerオプションの否定形を使えばよい。
touch -t YYYYMMDDhhmm.s1 1secbefore.tmp # 基準日時の1秒前
find /TARGET/DIR \( \! -newer 1secbefore.tmp \)
rm 1secbefore.tmp
それでは「等しい」としたいならどうすればよいか。それには基準日時のファイルとその1秒前のファイルの2つを作り、「基準日時1秒前より新しい」かつ「基準日時を含むそれ以前」という条件にすればよい。
touch -t YYYYMMDDhhmm.ss thattime.tmp
touch -t YYYYMMDDhhmm.s1 1secbefore.tmp
find /TARGET/DIR -newer 1secbefore.tmp \( \! -newer thattime.tmp \)
rm 1secbefore.tmp thattime.tmp
2.n秒前より新しい、古い、等しい
基準日時との新旧比較のやり方がわかったのだから、あとは現在日時のn秒前、およびn-1秒前という計算ができれば実現できることになる。
それはどうやるのかといえば、シェルスクリプトで時間計算を一人前にこなすにて書いていた。そう、日常時間(YYYYMMDDhhmmss)をUNIX時間に変換して引き算し、それを元に戻せばいいのだ。そしてそのために、POSIXの範囲で動くコマンド"utconv"を自作していたのだ。
それでは、1分30秒前より新しい、等しい、古いファイルを抽出するシェルスクリプトを書いてみよう。
now=$(date '+%Y%m%d%H%M%S')
t0=$(echo $now |
utconv |
awk '{print $0-60*1-30}' |
utconv -r |
sed 's/..$/.&/' )
touch -t $t0 thattime.tmp
find /TARGET/DIR -newer thattime.tmp
rm thattime.tmp
now=$(date '+%Y%m%d%H%M%S')
t1=$(echo $now |
utconv |
awk '{print $0-60*1-31}' |
utconv -r |
sed 's/..$/.&/' )
touch -t $t1 1secbefore.tmp
find /TARGET/DIR \( \! -newer 1secbefore.tmp \)
rm 1secbefore.tmp
now=$(date '+%Y%m%d%H%M%S')
t0=$(echo $now |
utconv |
awk '{print $0-60*1-30}' |
utconv -r |
sed 's/..$/.&/' )
t1=$(echo $now |
utconv |
awk '{print $0-60*1-31}' |
utconv -r |
sed 's/..$/.&/' )
touch -t $t0 thattime.tmp
touch -t $t1 1secbefore.tmp
find /TARGET/DIR -newer 1secbefore.tmp \( \! -newer thattime.tmp \)
rm thattime.tmp 1secbefore.tmp