2008-10-10 104 views
410

如何確定腳本本身內的Bash腳本文件的名稱?如何知道Bash腳本中的腳本文件名?

如果我的腳本在文件runme.sh,那麼我將如何讓它顯示「你正在運行runme.sh」消息而不硬編碼?

+3

相似[[bash腳本可以告訴它存儲在哪個目錄?](http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in ) – Rodrigue 2012-07-05 08:22:34

+0

有關目錄,請參閱:[從內部獲取Bash腳本的源目錄](https://stackoverflow.com/q/59895/55075)。 – kenorb 2017-07-19 18:39:54

回答

427
me=`basename "$0"` 

對於通過一個符號,通常是不是你想要的閱讀(你通常不希望用戶混淆這種方式),嘗試:

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

海事組織,那將產生混淆輸出。 「我跑了foo.sh,但它說我正在運行bar.sh!?必須是一個bug!」此外,具有不同名稱符號鏈接的目的之一是根據其名稱(在某些平臺上認爲gzip和gunzip)提供不同的功能。

+2

這裏的基地名稱很不錯。 – dmckee 2008-10-10 17:23:52

+17

$ 0爲您提供了通過其調用腳本的名稱,而不是實際腳本文件的實際路徑。 – 2008-10-10 17:48:16

+3

它工作除非你被稱爲通過符號鏈接。但即使如此,它通常也是你想要的,IME。 – Tanktalus 2008-10-10 17:50:27

0

回聲「您正在運行$ 0」

+0

不是bash腳本,是完整路徑。 – 2016-05-23 01:45:31

5

您可以使用$ 0到確定你的腳本名稱(完整路徑) - 獲得腳本名稱只有你可以修剪這個變量與

basename $0 
56

如果腳本名稱中有空格,更可靠的方法是使用"$0""$(basename "$0")" - 或在MacOS上:"$(basename \"$0\")"。這可以防止名稱以任何方式變形或解釋。一般來說,總是在shell中雙引號變量名是一個好習慣。

0

$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對他想要的有點含糊不清。

19

要回答Chris Conway,在Linux上(至少)你可以這樣做:

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

的readlink打印出一個符號鏈接的價值。如果它不是符號鏈接,則會打印文件名。 -n告訴它不要打印換行符。 -f告訴它完全遵循鏈接(如果一個符號鏈接是另一個鏈接的鏈接,它也可以解決這個問題)。

19

如果你想它不帶路徑,那麼你會使用${0##*/}

11

這些答案是他們國家的情況下,正確的,但如果您運行使用「源」關鍵字從另一個腳本的腳本存在還是個問題(以便它運行在同一個shell中)。在這種情況下,您將獲得調用腳本的$ 0。在這種情況下,我不認爲有可能獲得腳本本身的名稱。

這是一個邊緣案例,不應該認真對待。如果你直接從另一個腳本運行腳本(沒有'源'),使用$ 0就可以工作。

148

隨着的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" 
194
 
# ------------- 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 ------------- # 

# Notice on the next line, the first argument is called within double, 
# and single quotes, since it contains two words 

$ /misc/shell_scripts/check_root/show_parms.sh "'hello there'" "'william'" 

# ------------- RESULTS ------------- # 

# arguments called with ---> 'hello there' 'william' 
# $1 ----------------------> 'hello there' 
# $2 ----------------------> 'william' 
# path to me --------------> /misc/shell_scripts/check_root/show_parms.sh 
# parent path -------------> /misc/shell_scripts/check_root 
# my name -----------------> show_parms.sh 

# ------------- END ------------- # 
8

重新:Tanktalus的(接受的)應答上面,一個略微更清潔的方式是使用:

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

如果您的腳本來自另一個bash腳本,您可以使用:

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

我同意,如果你的目標是提供反饋給用戶這將是混亂的取消引用符號鏈接,但有些時候你需要得到規範名稱的腳本或其他文件,這是最好的方法,imo。

54

$BASH_SOURCE在採購腳本時給出正確的答案。

然而,這包括通路,以便獲得腳本只有文件名,使用方法:

$(basename $BASH_SOURCE) 
5
this="$(dirname "$(realpath "$BASH_SOURCE")")" 

這解決符號鏈接(真實路徑確實是),處理空間(雙引號做到這一點),並且將即使源代碼(./myscript)或其他腳本調用($ BASH_SOURCE處理該腳本),也可以找到當前腳本名稱。經過了這一切,這是好事,在環境變量中保存此重新使用或用於其他地方(這=)便於複製...

10

我發現這條線總是工作,無論文件是否是作爲腳本來源或運行。

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

如果你想跟隨符號連接你上面,遞歸或非遞歸的道路上使用readlink

使用BASH_SOURCE環境變量及其關聯FUNCNAME來解釋單行工作的原因。

BASH_SOURCE

數組變量,其成員是其中在FUNCNAME數組變量對應的殼函數名定義的源文件名。殼功能$ {FUNCNAME [$ i]於}在文件$ {BASH_SOURCE [$ i]於}定義和從$稱爲{BASH_SOURCE [$ I + 1]}。

FUNCNAME

陣列包含當前在執行調用堆棧的所有殼功能的名稱的變量。索引爲0的元素是任何當前正在執行的shell函數的名稱。最底部的元素(索引最高的元素)是「主」。這個變量只有在shell函數執行時才存在。分配到FUNCNAME沒有效果並且返回一個錯誤狀態。如果FUNCNAME沒有設置,它就失去了特殊的意義,即使後來重新定義它。

該變量可以與BASH_LINENO和BASH_SOURCE一起使用。 FUNCNAME的每個元素在BASH_LINENO和BASH_SOURCE中都有對應的元素來描述調用堆棧。例如,$ {FUNCNAME [$ i]}在行號爲$ {BASH_LINENO [$ i]}的文件$ {BASH_SOURCE [$ i + 1]}中被調用。調用者內建使用此信息顯示當前調用堆棧。

[來源:Bash的手冊]

2

信息感謝比爾·埃爾南德斯。我添加了一些我正在採用的偏好。

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

乾杯

-5

財產以後也是這樣嗎?

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 
6

如果你調用的shell腳本一樣

/home/mike/runme.sh 

$ 0全稱

/home/mike/runme.sh 

基名$ 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" 
1
echo "$(basename "`test -L ${BASH_SOURCE[0]} \ 
        && readlink ${BASH_SOURCE[0]} \ 
        || echo ${BASH_SOURCE[0]}`")" 
1

bash你可以使用$0腳本文件名。一般$1,$2等都是用來訪問CLI參數的。同樣,$0用於訪問觸發腳本的名稱(腳本文件名)。

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

由於被問及文件名的一些意見不帶擴展,這裏是一個例子,如何來實現這一目標:

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

享受!