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


606

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

スクリプトがfileにある場合、runme.shハードコーディングせずに「You are running runme.sh」メッセージを表示するにはどうすればよいですか?


3
[その中に保存され、どのディレクトリbashスクリプトを伝えることができる?]同様の(へstackoverflow.com/questions/59895/...
Rodrigue

ディレクトリについては、「Bashスクリプトのソースディレクトリをから取得する」を参照してください。
ケノーブ2017

回答:


631
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


40
$ 0は、実際のスクリプトファイルの実際のパスではなく、スクリプトが呼び出された名前を示します。
Chris Conway、

4
symlink経由で呼び出されている場合を除き、機能します。しかし、それでも、それは通常、とにかく欲しいものです、IME。
Tanktalus、2008年

78
呼び出されるのではなく、ソースが提供されるスクリプトでは機能しません。
Charles Duffy

1
@Charles Duffy:以下のDimitre Radoulovの回答を参照してください。
Serge Wautier、2011年

8
-1、1。readlinkはシンボリックリンクを1つだけ移動します。2。$0最初の例は単語分割の対象$0です。3。コマンドラインスイッチとして処理できる位置でbasename、readlink、echoに渡されます。。代わりにme=$(basename -- "$0")、読みやすさを犠牲にして、より効率的にお勧めしme=${0##*/}ます。シンボリックリンクの場合、me=$(basename -- "$(readlink -f -- "$0")")gnu utilsを想定しています。それ以外の場合、ここでは記述しない非常に長いスクリプトになります。
Score_Under

246
#  -  -  -  -  -  - - 脚本  -  -  -  -  -  - - #


#!/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 -------------##------------- CALLED -------------#

#次の行に注目してください。最初の引数はdouble内で呼び出されます。 #次の行に注目してください。最初の引数はdouble内で呼び出されます。 
#と単一引用符、2つの単語が含まれているため#と単一引用符、2つの単語が含まれているため

$ /misc/shell_scripts/check_root/show_parms.sh "'hello there'" "'william'"/ miscの/ shell_scripts / check_root / show_parms sh 「こんにちは」「ウィリアム」 

#  -  -  -  -  -  - - 結果  -  -  -  -  -  - - ##  -  -  -  -  -  - - 結果  -  -  -  -  -  - - #

#---> 'hello there' 'william'で呼び出される引数#---> 'hello there' 'william'で呼び出される引数
#$ 1 ----------------------> 'こんにちは'#$ 1 ----------------------> 'こんにちは'
#$ 2 ----------------------> 'william'#$ 2 ----------------------> 'william'
#私へのパス--------------> /misc/shell_scripts/check_root/show_parms.sh#私へのパス--------------> /misc/shell_scripts/check_root/show_parms.sh
#親パス-------------> / misc / shell_scripts / check_root#親パス-------------> / misc / shell_scripts / check_root
#私の名前-----------------> show_parms.sh#私の名前-----------------> show_parms.sh

#  -  -  -  -  -  - - 終わり  -  -  -  -  -  - - ##  -  -  -  -  -  - - 終わり  -  -  -  -  -  - - #


1
どのようにすればちょうどshow_params、つまりオプションの拡張子のない名前を取得できますか?
Acumenus 2015

スクリプトが別のフォルダから呼び出された場合は機能しません。パスはに含まれてい${0##*/}ます。GitBashを使用してテストされています。
AlikElzin-kilaka 2015

1
上記は.bash_loginスクリプトからは機能しませんでしたが、$ BASH_SOURCEのDimitre Radoulovソリューションはうまく機能します。
ジョン

@ジョン確かにあなたは.bash_profileを意味しますか?または、代わりに.bashrc?ただし、それらの呼び出し方法やソース方法には微妙な違いがあることを知っておく必要があります。私はすごく疲れていますが、もし私が正しく考えているのなら、それが問題である可能性が非常に高いでしょう。重要なのは、ローカルシステムからではなく、sshなどを介してリモートでシステムにログインしている場合です。
プリフタン

193

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"

24
すごい!それが./scrip.shとsource ./script.shの両方で機能する答えです
zhaorufei

4
これは私が望んでいることであり、「dirname $BASE_SOURCE」を使用してスクリプトが配置されたディレクトリを簡単に取得できます。
Larry Cai、

2
自己削除スクリプトを作成するときに、私はほとんどその違いを理解しました。幸いにも、「rm」は「rm -i」にエイリアスされていました:)
kervin

とにかく。./s bashの代わりに./sという名前を取得するには?$ 1が常に./sに設定されているわけではないことを発見しました...
David

1
それはBASH_SOURCEにありますね。
Dimitre Radoulov 2013

69

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

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

$(basename $BASH_SOURCE) 

2
この回答は、自己文書化されたコードを利用するため、私見が最良の回答です。$ BASH_SOURCEはドキュメントを読まなくても完全に理解できますが、たとえば$ {0 ## * /}は理解できません
Andreas M. Oberheim

のように実行すると. <filename> [arguments]$0呼び出し元のシェルの名前が表示されるため、この答えはより価値があると私は信じています。確かに少なくともOSXでは。
Mihir

68

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


2
+1は直接回答+簡潔です。シンボリックリンク機能が必要な場合は、以下を参照してください。TravisB. Hartwellの回答。
Trevor Boyd Smith、

26

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


そして、オプションのファイル拡張子なしでそれが欲しい場合はどうなりますか?
Acumenus 2015

拡張子を削除するには、「$ {VARIABLE%.ext}」を試すことができます。VARIABLEは$ {0 ## * /}から取得した値で、「。ext」は削除する拡張子です。
BrianV

19

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

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

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


2
-(n)は無害ですが、$(...)構造によってトリムされるため、必要ありません。
zhaorufei

16

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

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

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

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

BASH_SOURCE

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

FUNCNAME

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

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

[出典:バッシュマニュアル]


2
対話型のセッションからファイルaaのコンテンツがであると想定)でソースを取得すると機能しますecho "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"-次に、aパスが表示されます。しかし、スクリプトbを記述source aして実行すると./bbのパスが返されます。
PSkocik 2015年

12

これらの回答は、記載されているケースでは正しいですが、「source」キーワードを使用して別のスクリプトからスクリプトを実行すると(同じシェルで実行されるように)、依然として問題があります。この場合、呼び出しスクリプトの$ 0を取得します。この場合、スクリプト自体の名前を取得することはできないと思います。

これはエッジケースであり、真剣に受け止めるべきではありません。別のスクリプトからスクリプトを直接(「ソース」なしで)実行する場合は、$ 0を使用できます。


2
あなたは非常に良い点を持っています。エッジケースIMOではありません。ただし、解決策があります。上記のDimitre Radoulovの回答を
Serge Wautier '27 / 10/27

10

一部のコメントでは拡張子のないファイル名について尋ねられたため、これを実現する方法の例を次に示します。

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

楽しい!


9

Re:上記のTanktalusの(受け入れられた)答えは、少しすっきりとした方法を使用することです。

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

スクリプトが別のbashスクリプトから供給されている場合は、以下を使用できます。

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

あなたの目的がユーザーにフィードバックを提供することである場合、シンボリックリンクを逆参照することは混乱を招くことに同意しますが、正規の名前をスクリプトまたは他のファイルに取得する必要がある場合がありますが、これが最善の方法です、imo。


1
sourcedスクリプト名をお寄せいただきありがとうございます。
Fredrick Gauss

8

$ 0を使用してスクリプト名を(フルパスで)判別できます。その変数をトリミングできるのはスクリプト変数だけです。

basename $0

8

あなたのようなシェルスクリプトを呼び出す場合

/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"

7
this="$(dirname "$(realpath "$BASH_SOURCE")")"

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


3
FYI realpathは組み込みのBASHコマンドではありません。これは、特定のディストリビューションでのみ使用可能なスタンドアロンの実行可能ファイルです
StvnW

4

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

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

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


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

2

$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は彼が何を望んでいたかについて少し曖昧です。


上記の私の回答にこれに対する回答を追加しましたが、これが本当に欲しいものである(または、私が現在
理解

2
script.shの代わりにlinktoscriptを出力するのは機能であり、バグではないと思います。いくつかのUNIXコマンドは、その名前を使用して動作を変更します。例はvi / ex / viewです。
mouviciel 2009年

@Tanktalus:ファイルの実際の場所に基づいて動作を変更したい場合があります-以前のプロジェクトでは、「アクティブブランチ」スクリプトがありました。取りかかっている; これらのツールは、適切なファイルに対して実行するためにチェックアウトされているディレクトリを見つけることができます。
アンドリューアイレット

2

情報は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
}

乾杯


1

短く、明確でシンプル、 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

これが私が思いついたもので、Dimitre Radoulovの回答(ちなみに私は賛成しています)に触発されています

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

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

スクリプトを呼び出す方法に関係なく

. path/to/script.sh

または

./path/to/script.sh


-6

このような何か?

export LC_ALL=en_US.UTF-8
#!/bin/bash
#!/bin/sh

#----------------------------------------------------------------------
start_trash(){
ver="htrash.sh v0.0.4"
$TRASH_DIR  # url to trash $MY_USER
$TRASH_SIZE # Show Trash Folder Size

echo "Would you like to empty Trash  [y/n]?"
read ans
if [ $ans = y -o $ans = Y -o $ans = yes -o $ans = Yes -o $ans = YES ]
then
echo "'yes'"
cd $TRASH_DIR && $EMPTY_TRASH
fi
if [ $ans = n -o $ans = N -o $ans = no -o $ans = No -o $ans = NO ]
then
echo "'no'"
fi
 return $TRUE
} 
#-----------------------------------------------------------------------

start_help(){
echo "HELP COMMANDS-----------------------------"
echo "htest www                 open a homepage "
echo "htest trash               empty trash     "
 return $TRUE
} #end Help
#-----------------------------------------------#

homepage=""

return $TRUE
} #end cpdebtemp

# -Case start
# if no command line arg given
# set val to Unknown
if [ -z $1 ]
then
  val="*** Unknown  ***"
elif [ -n $1 ]
then
# otherwise make first arg as val
  val=$1
fi
# use case statement to make decision for rental
case $val in
   "trash") start_trash ;;
   "help") start_help ;;
   "www") firefox $homepage ;;
   *) echo "Sorry, I can not get a $val   for you!";;
esac
# Case stop

5
-1は質問に回答せず(スクリプトの名前を見つける方法は示していません)、非常にバグの多いスクリプトのわかりにくい例です。
スコア_2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.