組み込みのtest
および[
ユーティリティには、シェルが「POSIXモード」で実行されている場合でも、ほとんどのシェルで-nt
(「より新しい」)および-ot
(「より古い」)テストがあります(私がアクセスできるシステム上の同じ名前)。これらのテストは、2つのファイルの変更タイムスタンプを比較するためのものです。文書化されたセマンティクスは実装間で若干異なります(一方または他方のファイルが存在しない場合に何が起こるかに関して)が、それらは test
ユーティリティのPOSIX仕様 には含まれていません。
これらは、
test
ユーティリティの歴史的な実装に組み込まれているtest
ユーティリティに含まれていないため、[KornShell]シェルから条件付きコマンドが削除されたとき、sh
ユーティリティに持ち越されませんでした。
/bin/sh
シェルスクリプト内のファイル間の変更タイムスタンプを比較し、次のように1つのファイルが他のファイルよりも新しいかどうかに応じてアクションを実行するとします
if [ "$sigfile" -nt "$timestamp" ] ||
[ "$sigfile.tmp" -nt "$timestamp" ]
then
return
fi
... make
(スクリプトの残りの部分を控えめに言っても扱いにくくする)を除いて、他にどのようなユーティリティを使用できますか?または、「sh
の歴史的な実装」でスクリプトを実行する予定がない、または固有のシェルのような記述を辞任するとは思わないbash
?
POSIXLY:
f1=/path/to/file_1
f2=/path/to/file_2
if [ -n "$(find -L "$f1" -Prune -newer "$f2")" ]; then
printf '%s is newer than %s\n' "$f1" "$f2"
fi
ファイルへの絶対パスを使用すると、ファイル名の誤検知を防ぐことができます。改行のみが含まれます。
相対パスを使用する場合は、find
コマンドを次のように変更します。
find -L "$f1" -Prune -newer "$f2" -exec echo . \;
これは、最も古いUnixコマンドの1つであるls
を使用する場合である可能性があります。
x=$(ls -tdL -- "$a" "$b")
[ "$x" = "$a
$b" ]
Aがbよりも新しい場合、結果はtrueです。
興味深い質問があり、最初に確認する必要がある主張をしました。
私はの行動をチェックしました:
$Shell -c '[ Makefile -nt SCCS/s.Makefile ] && echo newer'
様々な砲弾を搭載。結果は次のとおりです。
bash機能しません-何も印刷されません。
bosh機能する
dash機能しません-何も印刷されません。
ksh88機能しません-何も出力されません。
ksh93機能する
mksh機能しません-何も出力されません。
poshの出力:posh:[:-nt:予期しない演算子/オペランド
yash機能する
zsh新しいバージョンで機能します、古いバージョンでは何も印刷されません
したがって、9つのシェルのうち4つが-nt機能をサポートし、正しく実装します。 は、1秒未満のタイムスタンプの粒度をサポートする最近のプラットフォームのタイムスタンプを比較できます。私が選択したファイルは通常、タイムスタンプが数マイクロ秒しか異なることに注意してください。
動作しているfind
実装を見つける方が簡単なので、置き換えることをお勧めします
if [ "$file1" -nt "$file2" ] ; then
echo newer
fi
find
ベースの式。
if [ "$( find "$file1" -newer "$file2" )" ]; then
echo newer
fi
少なくとも$file1
は改行だけではありません。
if [ "$( find -L "$file1" -newer "$file2" -exec echo newer \; )" ]; then
echo newer
fi
少し遅いですが、正しく動作します。
ところで:makeについてすべてのmake実装について話すことはできませんが、SunPro Make
は約から、ナノ秒単位の時間比較をサポートしています。 20年間、smake
とgmake
はこの機能を最近追加しました。