/bin がシンボリックリンクなのに、なぜ $0=/bin/foo になるのか

/bin がシンボリックリンクなのに、なぜ $0=/bin/foo になるのか

私はbashスクリプトをインストールし/usr/bin/app.sh/usr/bin/lib.sh

app.sh含まれるもの

source "/usr/bin/lib.sh"

そしてlib.sh含まれる

if [ "/usr/bin/app.sh" == "$0"] ...

app.shシェルから実行すると、このテストは失敗します。$0これは、実際には だからです/bin/app.sh。ファイルシステム上では、/binは へのシンボリックリンクです。/usr/bin

環境に惑わされることなく、 が(ではなく)lib.shに含まれているかどうかを判断するための最良の方法は何ですか? シンボリックリンクのない絶対パスで十分だと思っていましたが、どうやらそうではないようです。app.shother-app.sh

答え1

2 つのファイルが同じかどうかを確認するには、次のように表示されるインデックス (inode) 番号を確認する必要があります。

stat -L -c %i FilePath

したがって、あなたの小切手は次のようになります:

if [ $(stat -L -c %i "/usr/bin/app.sh") == $(stat -L -c %i "$0") ] ...

これは、ディレクトリ パス内のリンク、またはファイル自体へのシンボリック リンクやハード リンクに関係なく機能します。

厳密に言えば(この点を指摘してくれた @ilkkachu に感謝します)、同じ名前の 2 つの異なるファイルが 2 つの異なるファイル システム上で同じ inode を持つ可能性は非常に低いです。これを回避するには、比較にデバイス番号を含めます。

if [ $(stat -L -c %d:%i "/usr/bin/app.sh") == $(stat -L -c %d:%i "$0") ] ...

答え2

readlink -f /path/to/whatever/usr/bin/app.sh正規のパス(例にあるもの)がわかります。

からマニュアルページ:

指定された名前のすべてのコンポーネントのすべてのシンボリックリンクを再帰的にたどって正規化します。最後のコンポーネントを除くすべてのコンポーネントが存在する必要があります。

関連情報