なぜ 'BASH_SOURCE'を使用してスクリプトが実行されている現在のディレクトリを取得できますか?

なぜ 'BASH_SOURCE'を使用してスクリプトが実行されている現在のディレクトリを取得できますか?

source.)を使って$HOME/.bash_profileローカルファイルからコマンドを実行します$HOME/.dotfiles/.bash_profile

[[ -r "$HOME/.dotfiles/.bash_profile" ]] && . "$HOME/.dotfiles/.bash_profile" 

今、$HOME/.dotfiles/.bash_profilein$0値はです。これは、実行中のスクリプトの現在のディレクトリを検索する"-bash"ために使用できないことを意味します。dirname

BASH_SOURCE実行スクリプトの名前で埋めなければならないことを読みました(そしてうまくいきます!)。

しかし、なぜ実行スクリプトをシェル関数に対応するソースファイル名の配列として定義すると、BASH_SOURCE実行スクリプト名は保存されますか?man bash

また、BASH_SOURCE配列として定義されているため、スクリプトが実行されている現在のディレクトリを取得するために次のように使用することは、複数の値を保持できるため安全ではありませんdirname $BASH_SOURCE

man bash:

BASH_SOURCE
   An array variable whose members are the source filenames
   where the corresponding shell function names in the FUNCNAME array 
   variable are defined. The shell function ${FUNCNAME[$i]} is defined
   in the file ${BASH_SOURCE[$i]} and called from ${BASH_SOURCE[$i+1]}.

答え1

ところで、BASH_SOURCE実行スクリプトはシェル関数に対応するソースファイル名の配列としてman bashに定義されていますが、なぜ実行スクリプト名を保存するのですか?

なぜ?それはおそらく、メインスクリプトのファイル名を使うのが便利だからです。

マニュアルの説明を見てみましょう。

BASH_SOURCE
FUNCNAME配列変数に対応するシェル関数名を定義するソースファイル名がメンバーである配列変数。シェル関数は${FUNCNAME[$i]}ファイルに定義されており、${BASH_SOURCE[$i]}以下から派生します。${BASH_SOURCE[$i+1]}

FUNCNAME
現在実行中の呼び出しスタック内のすべてのシェル関数の名前を含む配列変数。インデックス0の要素は、現在実行中のシェル関数の名前です。一番下の要素(インデックスが最も高い要素)は「main」です。

foo基本スクリプトから呼び出される関数には、定義されたファイル名が${FUNCNAME[0]}含まれfooています。デフォルトのスクリプトファイルの名前が含まれています。${BASH_SOURCE[0]}foo${FUNCNAME[1]}main${BASH_SOURCE[1]}

for FUNCNAME、関数の外部で空であることを明示的に表します。なぜならBASH_SOURCE違うからです。常にデフォルトのスクリプトファイル名の拡張子を最後に追加するのはBASH_SOURCEかなり論理的です。関数の呼び出しと戻りには、前に要素を追加/削除するだけです。

そうは言いませんが、BASH_SOURCEソーススクリプト(. foo.shまたは同様のもの)も追跡します。FUNCNAMEまた、関数が呼び出されない限り表示されませんが、実際にsource実際の関数がある場合に表示されます。

また、BASH_SOURCE配列として定義されているため、スクリプトが実行されている現在のディレクトリを取得するために次のように使用することは、複数の値を保持できるため安全ではありませんdirname $BASH_SOURCE

これが質問なのか、ステートメントなのかよく分からない。ただし、インデックスなしで配列を参照することは、インデックスを使用するのと同じです0$BASH_SOURCEこれも真で、${BASH_SOURCE[0]}現在関数が定義されているファイルの名前も含みます。 (似たようなものが必要なため、基本スクリプト用ではありません${BASH_SOURCE[ ${#BASH_SOURCE[@]} - 1 ]}。)

ファイル名はまだ./foo.shまたは類似している可能性があるfoo.shため、dirname有用な情報を提供できない可能性があります。

関連情報