スクリプト内でソースtcshまたはbashシェルスクリプトのパスを決定する方法

スクリプト内でソースtcshまたはbashシェルスクリプトのパスを決定する方法

どのような方法がありますか?源泉シェルスクリプトは独自のパスを見つけますか?私の主な関心事はbash私の同僚の一部ですtcsh

ソーシングによって現在のシェルでコマンドが実行されるため、ここでは幸運ではない可能性があります。したがって、$0まだソーススクリプトではなく、現在のシェルを呼び出します。最良のアイデアは、source $script $script最初の位置パラメータに必要な情報を含めることです。誰でも良い方法がありますか?

明らかに言えば、私は購入スクリプトを実行する代わりに:

source foo.bash

答え1

では、ファイルtcshがソースまたはファイルが実行されている場合、$_スクリプトの先頭にその場所が含まれます。$0

#!/bin/tcsh
set sourced=($_)
if ("$sourced" != "") then
    echo "sourced $sourced[2]"
endif
if ("$0" != "tcsh") then
    echo "run $0"
endif

大きな打撃を受けた場合:

#!/bin/bash
[[ $0 != $BASH_SOURCE ]] && echo "Script is being sourced" || echo "Script is being run"

答え2

変数を活用すればいいと思います$BASH_SOURCE。実行パスを返します。

スクリプト例:

印刷スクリプトのパス.sh:

#!/usr/bin/env bash

echo "$BASH_SOURCE"

実行可能にする:

chmod +x print_script_path.sh

このスクリプトのさまざまな場所に対して例を実行して出力します。

pbm@tauri ~ $ /home/pbm/print_script_path.sh 
/home/pbm/print_script_path.sh
pbm@tauri ~ $ ./print_script_path.sh
./print_script_path.sh
pbm@tauri ~ $ source /home/pbm/print_script_path.sh 
/home/pbm/print_script_path.sh
pbm@tauri ~ $ source ./print_script_path.sh
./print_script_path.sh

次に、パスが相対パスであることを確認する必要があります。相対的なものでなければ、すべてが大丈夫でしょう。その場合は、パスを確認しpwd/接続するために使用できます$BASH_SOURCE

答え3

このソリューションはtcshではなくbashでのみ機能します。${BASH_SOURCE[0]}関数内でパスを見つけようとすると、通常提供されている答えは機能しません。

私はこの行がファイルがソースファイルとして実行されているかスクリプトで実行されているかにかかわらず、常に動作することを発見しました。

echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"

readlink再帰的または非再帰的にシンボリックリンクをたどるには、上記のパスを使用してください。

二重引用符は、パスのスペースが結果を配列に分割するのを防ぎ、に対してだけでなくecho使用されるすべてのコンテキストにも必要です。配列項目の間に単一のスペースが挿入されるため、echoパスに複数の連続したスペースがない場合は違いが隠されます。

以下は、他の提案ソリューションと比較するスクリプトです。source test1/test2/test_script.shまたはと呼んでくださいbash test1/test2/test_script.sh

#
# Location: test1/test2/test_script.sh
#
echo $0
echo $_
echo "${BASH_SOURCE}"
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"

cur_file="${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
cur_dir="$(dirname "${cur_file}")"
source "${cur_dir}/func_def.sh"

function test_within_func_inside {
    echo "${BASH_SOURCE}"
    echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
}

echo "Testing within function inside"
test_within_func_inside

echo "Testing within function outside"
test_within_func_outside
#
# Location: test1/test2/func_def.sh
#
function test_within_func_outside {
    echo "${BASH_SOURCE}"
    echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
}

1行のコードが機能する理由は、BASH_SOURCE環境変数と関連変数の使用によって説明できますFUNCNAME

BASH_SOURCE

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

機能名

現在実行中の呼び出しスタック内のすべてのシェル関数の名前を含む配列変数。インデックス0の要素は、現在実行中のシェル関数の名前です。一番下の要素(インデックスが最も高い要素)は「main」です。この変数は、シェル関数の実行時にのみ存在します。 FUNCNAME の割り当てが無効で、エラー状態を返します。 FUNCNAME が設定されていないと、後でリセットしても特殊属性が失われます。

この変数は BASH_LINENO と BASH_SOURCE で使用できます。 FUNCNAME の各要素には、BASH_LINENO と BASH_SOURCE に呼び出しスタックを記述する対応する要素があります。たとえば、${FUNCNAME[$i]} は ${BASH_SOURCE[$i+1]} ファイルの行番号 ${BASH_LINENO[$i]} から呼び出されます。組み込み呼び出し側はこの情報を使用して現在の呼び出しスタックを表示します。

[出典:Bashマニュアル]

答え4

徹底と検索者にとって、それは目的です...コミュニティWikiなので、他のシェルに対応するエントリを自由に追加してください(明らかに$ BASH_SOURCEは異なります)。

テスト.sh:

#! /bin/sh
called=$_
echo $called
echo $_
echo $0
echo $BASH_SOURCE

test2.sh:

#! /bin/sh
source ./test.sh

大きな打撃:

$./test2.sh
./test2.sh
./test2.sh
./test2.sh
./test.sh
$ sh ./test2.sh
/bin/sh
/bin/sh
./test2.sh
./test.sh

スプリント

$./test2.sh
./test2.sh
./test2.sh
./test2.sh

$/bin/sh ./test2.sh
/bin/sh
/bin/sh
./test2.sh

$

ジッシュ

$ ./test2.sh
./test.sh
./test.sh
./test.sh

$ zsh test.sh

echo
test.sh

$

関連情報