如何在脚本本身内确定Bash脚本文件的名称?
就像我的脚本在文件runme.sh
中一样,那么如何在没有硬编码的情况下显示“你正在运行runme.sh”消息呢?
答案 0 :(得分:545)
me=`basename "$0"`
通过符号链接 1 阅读,这通常不是你想要的(你通常不希望以这种方式混淆用户),试试:
me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"
IMO,这会产生令人困惑的输出。 “我跑了foo.sh,但它说我正在运行bar.sh!?一定是个bug!”此外,具有不同名称的符号链接的目的之一是根据其名称提供不同的功能(在某些平台上考虑gzip和gunzip)。
1 也就是说,要解析符号链接,以便当用户执行foo.sh
实际上是bar.sh
的符号链接时,您希望使用已解析的名称{{1而不是bar.sh
。
答案 1 :(得分:223)
# ------------- 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 ------------- #
答案 2 :(得分:178)
使用 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"
答案 3 :(得分:61)
如果脚本名称中包含空格,则更健壮的方法是使用"$0"
或"$(basename "$0")"
- 或在MacOS上使用"$(basename \"$0\")"
。这可以防止名称被破坏或以任何方式解释。通常,优良作法是始终在shell中引用变量名称。
答案 4 :(得分:60)
$BASH_SOURCE
会给出正确的答案。
然而,这包括仅获取脚本文件名的路径,请使用:
$(basename $BASH_SOURCE)
答案 5 :(得分:24)
如果你想要它没有路径,那么你将使用${0##*/}
答案 6 :(得分:19)
要回答Chris Conway,在Linux(至少)上你会这样做:
echo $(basename $(readlink -nf $0))
readlink打印出符号链接的值。如果它不是符号链接,则打印文件名。 -n告诉它不要打印换行符。 -f告诉它完全遵循链接(如果符号链接是指向另一个链接的链接,它也将解析该链接。)
答案 7 :(得分:13)
我发现此行始终有效,无论文件是源还是作为脚本运行。
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
如果你想遵循符号链接,请在你上面的路径上使用readlink
,递归或非递归。
使用BASH_SOURCE
环境变量及其关联FUNCNAME
来解释单行工作的原因。
BASH_SOURCE
一个数组变量,其成员是源文件名,其中定义了FUNCNAME数组变量中相应的shell函数名。 shell函数$ {FUNCNAME [$ i]}在文件$ {BASH_SOURCE [$ i]}中定义,并从$ {BASH_SOURCE [$ i + 1]}调用。
FUNCNAME
一个数组变量,包含当前在执行调用堆栈中的所有shell函数的名称。索引为0的元素是当前正在执行的shell函数的名称。最底部的元素(索引最高的元素)是“main”。此变量仅在执行shell函数时存在。对FUNCNAME的分配无效并返回错误状态。如果未设置FUNCNAME,则会丢失其特殊属性,即使它随后被重置。
此变量可与BASH_LINENO和BASH_SOURCE一起使用。 FUNCNAME的每个元素在BASH_LINENO和BASH_SOURCE中都有对应的元素来描述调用堆栈。例如,$ {FUNCNAME [$ i]}是从行号$ {BASH_LINENO [$ i]}的$ {BASH_SOURCE [$ i + 1]}调用的。内置调用者使用此信息显示当前调用堆栈。
[来源:Bash手册]
答案 8 :(得分:11)
这些答案对于他们声明的情况是正确的,但如果您使用'source'关键字从另一个脚本运行脚本(以便它在同一个shell中运行),则仍然存在问题。在这种情况下,您将获得$ 0的调用脚本。在这种情况下,我认为不可能获得脚本本身的名称。
这是一个边缘案例,不应该认真对待。如果直接从另一个脚本运行脚本(没有'source'),使用$ 0将起作用。
答案 9 :(得分:8)
由于一些评论询问了没有扩展名的文件名,以下是一个如何实现的例子:
FileName=${0##*/}
FileNameWithoutExtension=${FileName%.*}
享受!
答案 10 :(得分:8)
如果你的调用shell脚本喜欢
/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"
答案 11 :(得分:8)
Re:上面的Tanktalus(已接受)答案,稍微更清洁的方法是使用:
me=$(readlink --canonicalize --no-newline $0)
如果您的脚本来自其他bash脚本,则可以使用:
me=$(readlink --canonicalize --no-newline $BASH_SOURCE)
我同意,如果您的目标是向用户提供反馈,则解除引用符号链接会很困惑,但有时候您需要将规范名称添加到脚本或其他文件中,这是最好的方法,imo。
答案 12 :(得分:7)
您可以使用$ 0来确定您的脚本名称(使用完整路径) - 要获取脚本名称,您只能使用
修剪该变量basename $0
答案 13 :(得分:5)
this="$(dirname "$(realpath "$BASH_SOURCE")")"
这解析了符号链接(realpath就是这样),处理空格(双引号这样做),并且即使在sourced(./myscript)或其他脚本调用($ BASH_SOURCE处理它)时也会找到当前的脚本名称。毕竟,最好将其保存在环境变量中以便重复使用或在其他地方轻松复制(this =)......
答案 14 :(得分:3)
在bash
中,您可以使用$0
获取脚本文件名。通常$1
,$2
等用于访问CLI参数。同样$0
是访问触发脚本的名称(脚本文件名)。
#!/bin/bash
echo "You are running $0"
...
...
如果使用/path/to/script.sh
之类的路径调用脚本,则$0
也会为文件名提供路径。在这种情况下,需要使用$(basename $0)
来获取脚本文件名。
答案 15 :(得分: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
}
干杯
答案 16 :(得分:1)
$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对他想要的东西有点模棱两可。
答案 17 :(得分:1)
echo "$(basename "`test -L ${BASH_SOURCE[0]} \
&& readlink ${BASH_SOURCE[0]} \
|| echo ${BASH_SOURCE[0]}`")"
答案 18 :(得分:0)
在./self.sh
,~/self.sh
,source self.sh
,source ~/self.sh
上可以正常使用:
#!/usr/bin/env bash
self=$(readlink -f "${BASH_SOURCE[0]}")
basename=$(basename "$self")
echo "$self"
echo "$basename"
信用:我结合了多个答案来得到这个答案。
答案 19 :(得分: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.
答案 20 :(得分:0)
$0 将给出您正在运行的脚本的名称。创建脚本文件并添加以下代码
#!/bin/bash
echo "Name of the file is $0"
然后像这样从终端运行
./file_name.sh
答案 21 :(得分: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
答案 22 :(得分:0)
DIRECTORY=$(cd `dirname $0` && pwd)
我从另一个Stack Overflow问题 Can a Bash script tell what directory it's stored in? 得到了上述内容,但我认为它对此主题也很有用。
答案 23 :(得分:0)
echo“你正在运行$ 0”
答案 24 :(得分:-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