シンボリックリンク時間の比較

シンボリックリンク時間の比較

リンクがlnkfile通常の参照ファイルより古いかどうかを確認したいですreffile

Bashtestにはリンク逆参照機能が組み込まれているため、test lnkfile -ot reffile比較対象はlnkfileリンク自体ではありません。

test組み込み関数がシンボリックリンクに従わないようにする方法はありますか?それ以外の場合、シンボリックリンク時間をどのように比較できますか?

答え1

使用できる方法はありませんが、test使用できますfind

test "$(find reffile -prune -newer lnkfile)" && command

ここでは以前に出力が返されますfind。と同じオプションはありません。これは、文字列の長さがゼロでない場合に当てはまります。したがって、出力がある場合は実行してください。lnkfilereffiletesttest -nfindcommand


コメントでは、このソリューションを他のソリューションと比較するように求められました。stat。まず私はこのstat方法がとても良いと思いました。

比較のためにベンチマークテストをしてみました。私はテストを何度も繰り返して同様の結果を得ました。

$ time (for i in {1..1000}; do test "$(stat --format=%Z a)" -lt "$(stat --format=%Z b)" && echo foo > /dev/null ; done)

================
CPU 101%
CPU 104%
user    1.264
system  0.942
total   2.108

$ time (for i in {1..1000}; do test "$(find b -newer a)" && echo foo > /dev/null ; done)

================
CPU 104%
user    0.693
system  0.526
total   1.164

私にとってはほぼ2倍速いようですがfind、おそらく2つではなく1つのプロセスだからでしょうかstats?どのように比較するのか分かりません。他の関連側面が思い出されたらコメントを残してください。

以下のStéphane Chazelasのコメントによると、いくつかの異なる違いがあります。

他の違いは次のとおりです。find一つは標準です。statGNU実装が必要です。statこのstat方法は、同じ秒以内に変更されたファイルでは機能しません(ただし、findタイムスタンプの1秒未満の単位をサポートするシステムでは機能する必要があります)。任意のファイル名はサポートされていませんfindstat

ファイルのいずれかをstat()編集できない場合は、他の違いを見つけることができます。

答え2

私が知っている限り、bashは-otシンボリックリンクの逆参照などを防ぐバージョンを提供していません。

あなたができることは、GNU統計(シンボリックリンクがない場合は逆参照しない-L)を使用してmtimeエポックを数値的に比較することです。

if (( "$(stat --format=%Z lnkfile)" < "$(stat --format=%Z reffile)" )); then
    # lnkfile is older
fi

答え3

バージョン5.6以降(ナノ秒精度の場合)では、組み込みzsh関数を介してのみこれを実行できます。

zmodload zsh/stat
if 
  stat -LA lnktime -F '%021s%N' +mtime -- $lnkfile &&
    stat -A reftime -F '%021s%N' +mtime -- $reffile &&
    [[ $lnktime < $reftime ]]
then
  print -r -- $lnkfile is older than $reffile
fi

ファイル名に含まれる文字や非文字に関係なく動作し、タイムスタンプをナノ秒まで比較します。

GNU / Linuxを実行するx86_64 PCの一般的な倍精度浮動小数点は少なくとも不十分であるため、タイムスタンプを浮動小数点ではなく文字列(10進数文字列表現でナノ秒、0から30桁まで埋められる)で比較します。正確な保存数は次のとおりです。1548195897.775033155したがって、同じ100ナノ秒で今日修正された2つのファイルの違いを知ることはできません。

$ ((1548195897.775033155 < 1548195897.775033255)) && echo yes
$ [[ 1548195897775033155 < 1548195897775033255 ]] && echo yes
yes

関連情報