2008-10-10 101 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%.*} 

享受!