web-dev-qa-db-ja.com

Bashスクリプトのスクリプトファイル名を知るにはどうすればいいですか?

スクリプト自体の中のBashスクリプトファイルの名前を確認するにはどうすればよいですか。

私のスクリプトがrunme.shファイルにある場合のように、それをハードコーディングせずに「You are running runme.sh」というメッセージを表示させるにはどうすればよいですか。

512
Ma99uS
me=`basename "$0"`

シンボリックリンクを通して読むために1これは通常あなたが望んでいるものではありません(あなたは通常この方法でユーザーを混乱させたくありません)。

me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"

IMO、それは紛らわしい出力を生み出すでしょう。 「foo.shを実行しましたが、bar.shを実行しているということです!?バグである必要があります。」その上、異なる名前のシンボリックリンクを持つ目的の1つは、それが呼ばれる名前に基づいて異なる機能を提供することです(いくつかのプラットフォームでgzipとgunzipを考えてください)。


1 つまり、ユーザーが実際にfoo.shへのシンボリックリンクであるbar.shを実行するときに、bar.shではなく解決された名前foo.shを使用するようにシンボリックリンクを解決するためです。

538
Tanktalus
#------------- SCRIPT -------------#
 
#!/bin/bash

echo
echo "# arguments called with ---->  ${@}     "
echo "# \$1 ---------------------->  $1       "
echo "# \$2 ---------------------->  $2       "
echo "# path to me --------------->  ${0}     "
echo "# parent path -------------->  ${0%/*}  "
echo "# my name ------------------>  ${0##*/} "
echo
exit
 
# ------------- CALLED -------------#
 
#次の行に注意してください。最初の引数が呼び出されます二重、
#および一重引用符内。2つの単語が含まれているため。
 
 ( 'william' " 
 
#-------------結果-------------#
 
#引数---> 'hello there' 'william' 
#$ 1 ---------------------- > 'hello there' 
#$ 2 ----------------------> 'william' 
#私へのパス--- -----------> /misc/Shell_scripts/check_root/show_parms.sh
# parent path ------------->/misc/Shell_scripts/check_root 
#my name -----------------> show_parms.sh 
 
#---------- - - 終わり  -  -  -  -  -  - - #
229
Bill Hernandez

bash> = 3 の場合、次のように動作します。

$ ./s
0 is: ./s
BASH_SOURCE is: ./s
$ . ./s
0 is: bash
BASH_SOURCE is: ./s

$ cat s
#!/bin/bash

printf '$0 is: %s\n$BASH_SOURCE is: %s\n' "$0" "$BASH_SOURCE"
178

スクリプト名にスペースが含まれている場合、より確実な方法は"$0"または"$(basename "$0")" - 、あるいはMacOSでは"$(basename \"$0\")"です。これにより、名前が破損したり解釈されたりするのを防ぐことができます。一般に、シェルでは常に変数名を二重引用符で囲むことをお勧めします。

61
Josh Lee

$BASH_SOURCEは、スクリプトを調達するときに正しい答えを与えます。

ただし、これにはパスが含まれているため、スクリプトのファイル名だけを取得するには、次のように使用します。

$(basename $BASH_SOURCE) 
59
Zainka

あなたがパスなしでそれが欲しいなら、あなたは${0##*/}を使うでしょう

23
Mr. Muskrat

Chris Conway に答えるには、(少なくとも)Linuxでは、次のようにします。

echo $(basename $(readlink -nf $0))

readlinkはシンボリックリンクの値を表示します。シンボリックリンクでなければ、ファイル名を表示します。 -nは改行を表示しないように指示します。 -fは、リンクを完全にたどるように指示します(シンボリックリンクが別のリンクへのリンクである場合は、そのリンクも解決されます)。

19

ファイルがソースであるかスクリプトとして実行されているかに関係なく、この行は常に機能することがわかりました。

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

シンボリックリンクをたどる場合は、上記のパスにreadlinkを使用します(再帰的または非再帰的)。

ワンライナーが機能する理由は、BASH_SOURCE環境変数とそれに関連するFUNCNAMEの使用によって説明されます。

BASH_SOURCE

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

FUNCNAME

現在実行呼び出しスタックにあるすべてのシェル関数の名前を含む配列変数。インデックス0の要素は、現在実行中のシェル関数の名前です。一番下の要素(最も高いインデックスを持つ要素)は "main"です。この変数はShell関数が実行されているときだけ存在します。 FUNCNAMEへの割り当ては効果がなく、エラーステータスを返します。 FUNCNAMEが設定されていないと、後でリセットされても、FUNCNAMEはその特別なプロパティを失います。

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

[ソース:Bashマニュアル]

13
gkb0986

これらの答えはそれらが述べている場合には正しいですが、 'source'キーワードを使用して別のスクリプトからスクリプトを実行する場合(それが同じシェルで実行されるように)まだ問題があります。この場合は、呼び出し元のスクリプトの$ 0を取得します。そしてこの場合、スクリプト自体の名前を取得することは不可能だと思います。

これはEdgeのケースであり、真剣に考えるべきではありません。別のスクリプトから直接( 'source'なしで)スクリプトを実行する場合は、$ 0を使用しても問題ありません。

11
Jim Dodd

Re:Tanktalusの(受け入れられた)答えは、もう少しきれいな方法を使うことです:

me=$(readlink --canonicalize --no-newline $0)

あなたのスクリプトが他のbashスクリプトから供給されている場合は、次のものを使用できます。

me=$(readlink --canonicalize --no-newline $BASH_SOURCE)

あなたの目的がユーザへのフィードバックを提供することであればシンボリックリンクを間接参照することは混乱を招くことになると思いますが、スクリプトや他のファイルに正規名をつける必要がある場合があります。

8
simon

いくつかのコメントが拡張子なしのファイル名について尋ねたので、ここにそれを達成する方法の例があります:

FileName=${0##*/}
FileNameWithoutExtension=${FileName%.*}

楽しい!

8
Simon Mattes

シェルスクリプトを起動した場合

/home/mike/runme.sh

$ 0はフルネームです

 /home/mike/runme.sh

basename $ 0はベースファイル名を取得します

 runme.sh

そして、あなたはこの基本的な名前を次のように変数に入れる必要があります。

filename=$(basename $0)

追加のテキストを追加

echo "You are running $filename"

だからあなたのスクリプトは好きです

/home/mike/runme.sh
#!/bin/bash 
filename=$(basename $0)
echo "You are running $filename"
8
LawrenceLi

あなたは自分のスクリプト名を(フルパスで)決定するために$ 0を使うことができます - あなただけのスクリプト名を得るためにあなたはその変数をトリミングすることができます

basename $0
7
VolkA
this="$(dirname "$(realpath "$BASH_SOURCE")")"

これはシンボリックリンクを解決し(realpathはそれを行います)、スペースを処理し(二重引用符はこれを行います)、そして(。/myscript)を供給したり他のスクリプトによって呼び出されたりしても現在のスクリプト名を見つけます。結局のところ、再利用または他の場所へのコピーを簡単にするために、これを環境変数に保存しておくと便利です(this =)...

5
jcalfee314

bashでは、$0を使用してスクリプトファイル名を取得できます。一般に$1$2などはCLI引数にアクセスするためのものです。同様に$0はスクリプトを起動する名前(スクリプトファイル名)にアクセスすることです。

#!/bin/bash
echo "You are running $0"
...
...

/path/to/script.shのようなパスを使ってスクリプトを起動すると、$0もパスを含むファイル名を与えます。その場合は、スクリプトファイル名のみを取得するために$(basename $0)を使用する必要があります。

3
rashok

Bill Hernandezに感謝します。私が採用している設定をいくつか追加しました。

#!/bin/bash
function Usage(){
    echo " Usage: show_parameters [ arg1 ][ arg2 ]"
}
[[ ${#2} -eq 0 ]] && Usage || {
    echo
    echo "# arguments called with ---->  ${@}     "
    echo "# \$1 ----------------------->  $1       "
    echo "# \$2 ----------------------->  $2       "
    echo "# path to me --------------->  ${0}     " | sed "s/$USER/\$USER/g"
    echo "# parent path -------------->  ${0%/*}  " | sed "s/$USER/\$USER/g"
    echo "# my name ------------------>  ${0##*/} "
    echo
}

乾杯

2
linxuser
echo "$(basename "`test -L ${BASH_SOURCE[0]} \
                   && readlink ${BASH_SOURCE[0]} \
                   || echo ${BASH_SOURCE[0]}`")"
1
ecwpz91

$0は質問に答えません(私がそれを理解しているように)。デモンストレーション:

 $ cat script.sh 
#! /bin/sh
echo `basename $ 0` 
 $ ./script.sh 
 script.sh 
 $ ln script.sh linktoscript 
 $ ./linktoscript 
 linktoscript 

どのようにして./linktoscriptを印刷してscript.shを印刷するのですか?

[編集]上記のコメントの@ephemientによると、シンボリックリンクのことは人為的に思えるかもしれませんが、ファイルシステムリソースを表さないように$0をいじるのは可能です。 OPは彼が何を望んでいたかについて少しあいまいです。

1
Chris Conway

Dimitre Radoulov の答え (ところで、私はこれを支持しました) に触発されたものです。

script="$BASH_SOURCE"
[ -z "$BASH_SOURCE" ] && script="$0"

echo "Called $script with $# argument(s)"

スクリプトの呼び出し方法に関係なく

. path/to/script.sh

または

./path/to/script.sh
0

my_script.shの短く、明確でシンプルな、

#!/bin/bash

running_file_name=$(basename "$0")

echo "You are running '$running_file_name' file."

出力:

./my_script.sh
You are running 'my_script.sh' file.
0

echo "あなたは$ 0を実行しています"

0
mmacaulay
DIRECTORY=$(cd `dirname $0` && pwd)

Bashスクリプトは、どのディレクトリに格納されているのかを知ることができますかしかし、このトピックにも役立つと思います。

0
Koter84