シェルスクリプト:書き込み完了からn秒経過したファイルを表示する
シェルスクリプトを書く上で割と気にしているのは、確認する内容は単純な割に手作業でやると野暮ったい内容をどう書くかという話。環境はFreeBSD 13.0-RELEASE/amd64で確認していますが、その他のOSでは試していません。動かない事がある気がします。
今回の場合、n個のファイル一つ一つに対して現在時刻より300秒:5分以上経過していたらechoコマンドにより表示するという処理を書いています。
こういう処理が必要なときというのは、巨大なファイルが書き込まれている最中に誤ってそれを移動するなどの処理するなどして書きかけの壊れたファイルを持ってきてしまい、かつ書き込み完了時には完全なデータがロストしている、というような状況を防ぐ、そういう状況です。
01: #!/bin/sh
02:
03:
04: defaultIFS="${IFS}"
05: IFS="
06: "
07: nowdate=`env LANG=C date +%s`
08:
09: for args in $( ls ./*.jpg )
10: do
11: lastupdate=$( ls -lD %s ${args} | awk '{print $6}' )
12: if [ 300 -lt $(( ${nowdate} - ${lastupdate} )) ]
13: then
14: echo "${args}"
15: fi
16:
17: done
01: #!/bin/sh
02:
03:
04: defaultIFS="${IFS}"
05: IFS="
06: "
07: nowdate=`env LANG=C date +%s`
08:
09: for args in $( ls ./*.jpg )
10: do
11: lastupdate=$( ls -lD %s ${args} | awk '{print $6}' )
12: if [ 300 -lt $(( ${nowdate} - ${lastupdate} )) ]
13: then
14: echo "${args}"
15: fi
16:
17: done
解説:
01〜03行目までは割愛。
04〜06行目はお約束みたいなもので、csh系ではないsh系ではC言語で言うところの\tや半角スペースは区切り文字とIFS変数によって定義しているので、04行目でバックアップの上05〜06行目で\nの改行のみに再定義しなおしている。
07行目はスクリプトが実行した時刻を基にUNIX Epoch-timeから何秒経過した時間であるかを算出し、その値をnowdate変数に代入します。env LANG=C とかやってるのは単純に癖なのであってもなくてもそう変わらないはずです。
08行目は割愛。
08行目は割愛。
09、10、17行目はfor-eachループ文です。ls ./*.jpgの実行結果をIFS変数で定義された文字によってスプリットし、スプリットした文字列をargs変数に代入後11〜16行目を順次実行していきます。
11行目はls -lD %s ${args}が肝です。lsコマンドのオプションのlはともかくDは%sなどのdateコマンドで使うようなオプションを指定することができます。今回の場合%sとは"秒"を指します。特に他に何も指定しなかった場合はUNIX Epoch-timeを示します。実際にls -lD %sコマンドを実行してみればわかりますが、ファイルの作成時刻がUNIX Epoch-Timeに変更されます。あとはこれを抽出するためにawkを使用し、これをlastupdate変数に代入します。(awkコマンドのデリミタは" ":半角空白ですが、IFS変数の影響を受けません。面白いことですね)
12行目は、for-each文前に代入したnowdate変数からlastupdate変数を減算処理し、それを300とより大きいかを確認することによりTrueかFalseかを決定づけます。Trueなら13〜14行目を実行します。
15行目は割愛します。
ノンプログラマとしては、数年おきに出現する新しいコマンドや変更される機能を使うよりは、過去から未来まで確実に存在し仕様変更がなかなか行われなさそうなコマンド群で対応するほうが楽だったりします。そういう意味では"発展し続けるシステム"とは相性が悪いのかもしれません。これはCLIにとどまらずGUIにも言えることです。
コメント
コメントを投稿