如何确定脚本本身内部的Bash脚本文件的名称?
就像我的脚本在文件中一样runme.sh
,那么我如何在不进行硬编码的情况下显示“您正在运行runme.sh”消息呢?
如何确定脚本本身内部的Bash脚本文件的名称?
就像我的脚本在文件中一样runme.sh
,那么我如何在不进行硬编码的情况下显示“您正在运行runme.sh”消息呢?
Answers:
me=`basename "$0"`
要通读通常不是您想要的符号链接1(您通常不希望这样使用户感到困惑),请尝试:
me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"
海事组织,这将产生令人困惑的输出。“我运行了foo.sh,但这是说我正在运行bar.sh !?一定是bug!” 此外,具有不同名称的符号链接的目的之一是根据它的名称提供不同的功能(在某些平台上可以考虑一下gzip和gunzip)。
1也就是说,要解析符号链接,以便在用户执行时foo.sh
实际上是指向的符号链接bar.sh
,您希望使用解析的名称bar.sh
而不是foo.sh
。
$0
在第一个示例中,将进行单词拆分,3. $0
将其传递给基本名称,readlink和echo的位置应允许将其视为命令行开关。我建议改为me=$(basename -- "$0")
以牺牲可读性为代价,或者更有效地降低可读性me=${0##*/}
。对于符号链接,me=$(basename -- "$(readlink -f -- "$0")")
假设使用gnu utils,否则它将是一个很长的脚本,在这里我不会写。
#-------------脚本------------- ##-------------已调用------ -------#
#!/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
#注意下一行,第一个参数在双引号,#和单引号中被调用,因为它包含两个单词
$ / misc / shell_scripts / check_root / show_parms 。sh “'你好,那里”“ ”“威廉”
#-------------结果-------------#
#用--->'hello there''william' #$ 1 调用的参数---------------------->'hello there' #$ 2 ---- ------------------>'william' #我的路径--------------> / misc / shell_scripts / check_root / show_parms。 sh #父路径-------------> / misc / shell_scripts / check_root #我的名字-----------------> show_parms.sh
# - - - - - - - 结束 - - - - - - - #
show_params
,即没有任何可选扩展名的名称?
${0##*/}
。使用GitBash测试。
使用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"
dirname $BASE_SOURCE
”来获取脚本所在的目录。
$BASH_SOURCE
在采购脚本时给出正确的答案。
但是,这包括路径,因此仅获取脚本文件名,请使用:
$(basename $BASH_SOURCE)
. <filename> [arguments]
,$0
将给出调用方外壳的名称。至少可以肯定在OSX上。
如果脚本名称中有空格,一个更强大的方法是使用"$0"
或"$(basename "$0")"
-或在MacOS: "$(basename \"$0\")"
。这样可以防止以任何方式混淆或解释该名称。通常,良好的做法是始终在外壳程序中双引号。
要回答Chris Conway,至少在Linux上,您可以这样做:
echo $(basename $(readlink -nf $0))
readlink打印出符号链接的值。如果不是符号链接,则打印文件名。-n告诉它不打印换行符。-f告诉它完全跟随该链接(如果符号链接是到另一个链接的链接,则也会解析该链接)。
我发现此行始终有效,无论文件是源文件还是作为脚本运行。
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
如果要跟随符号链接readlink
在递归或非递归的路径上使用。
使用BASH_SOURCE
环境变量及其关联可以解释单行工作的原因FUNCNAME
。
BASH_SOURCE
一个数组变量,其成员是源文件名,在其中定义了FUNCNAME数组变量中的相应外壳函数名称。外壳函数$ {FUNCNAME [$ i]}在文件$ {BASH_SOURCE [$ i]}中定义,并从$ {BASH_SOURCE [$ i + 1]}中调用。
功能名称
一个数组变量,包含当前在执行调用堆栈中的所有shell函数的名称。索引为0的元素是任何当前正在执行的Shell函数的名称。最底部的元素(具有最高索引的元素)是“ main”。仅当执行Shell函数时,此变量才存在。分配给FUNCNAME无效,并返回错误状态。如果未设置FUNCNAME,则即使随后将其重置,它也会丢失其特殊属性。
此变量可以与BASH_LINENO和BASH_SOURCE一起使用。FUNCNAME的每个元素在BASH_LINENO和BASH_SOURCE中都有相应的元素来描述调用堆栈。例如,从文件$ {BASH_SOURCE [$ i + 1]}在行号$ {BASH_LINENO [$ i]}处调用了$ {FUNCNAME [$ i]}。内置呼叫方使用此信息显示当前呼叫堆栈。
[来源:Bash手册]
a
(假定a
内容为echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
),那么它将起作用-然后它将为您a
提供路径。但是,如果你写一个脚本b
与source a
它和运行./b
,它会返回b
的路径。
这些答案对于所陈述的情况是正确的,但是如果您使用'source'关键字从另一个脚本运行该脚本(以使其在同一外壳中运行),则仍然存在问题。在这种情况下,您将获得调用脚本的$ 0。在这种情况下,我认为不可能获得脚本本身的名称。
这是一个极端的情况,不应太当真。如果直接从另一个脚本(不带“源”)运行该脚本,则可以使用$ 0。
回复:上面的Tanktalus(已接受)答案,一种更简洁的方法是使用:
me=$(readlink --canonicalize --no-newline $0)
如果您的脚本来自另一个bash脚本,则可以使用:
me=$(readlink --canonicalize --no-newline $BASH_SOURCE)
我同意,如果您的目标是向用户提供反馈,则取消引用符号链接会令人困惑,但是有时您确实需要将规范名称获取到脚本或其他文件,这是imo的最佳方法。
source
d脚本名称。
this="$(dirname "$(realpath "$BASH_SOURCE")")"
这样可以解析符号链接(realpath可以做到),可以处理空格(使用双引号可以做到这一点),即使在源代码(../myscript)或被其他脚本调用($ BASH_SOURCE可以处理)的情况下,也可以找到当前的脚本名称。毕竟,最好将其保存在环境变量中以供重复使用或在其他位置轻松复制(this =)...
realpath
不是内置的BASH命令。它是一个独立的可执行文件,仅在某些发行版中可用
$0
没有回答这个问题(据我了解)。演示:
$ cat script.sh #!/ bin / sh echo`basename $ 0` $ ./script.sh script.sh $ ln script.sh链接脚本 $ ./linktoscript 链接脚本
如何./linktoscript
打印出来script.sh
?
[编辑]在上面的注释中,尽管@ephemient似乎是人为的,但还是有可能摆弄$0
它不代表文件系统资源。OP对他想要的内容有点含糊。
信息感谢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
}
干杯
简短,清晰,简单 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.
DIRECTORY=$(cd `dirname $0` && pwd)
我从另一个堆栈溢出问题中获得了上述内容,一个Bash脚本可以告诉它存储在哪个目录中吗?,但我认为这对于本主题也很有用。
这是我根据Dimitre Radoulov的回答(顺便说一句,我赞成)的启发得出的。
script="$BASH_SOURCE"
[ -z "$BASH_SOURCE" ] && script="$0"
echo "Called $script with $# argument(s)"
无论您如何调用脚本
. path/to/script.sh
要么
./path/to/script.sh
这样的东西?
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