如何确定脚本本身中的Bash脚本文件的名称?

就像如果我的脚本在文件runme.sh中,那么我如何让它显示“您正在运行runme.sh”消息而不硬编码?


当前回答

由于一些注释询问没有扩展名的文件名,这里有一个示例如何完成:

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

享受吧!

其他回答

如果不带路径,可以使用${0##*/}

我发现这一行总是有效的,无论文件是源文件还是作为脚本运行。

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

如果你想遵循符号链接,在上面得到的路径上使用readlink,递归或非递归。

单行程序工作的原因可以通过使用BASH_SOURCE环境变量及其关联的FUNCNAME来解释。

BASH_SOURCE An array variable whose members are the source filenames where the corresponding shell function names in the FUNCNAME array variable are defined. The shell function ${FUNCNAME[$i]} is defined in the file ${BASH_SOURCE[$i]} and called from ${BASH_SOURCE[$i+1]}. FUNCNAME An array variable containing the names of all shell functions currently in the execution call stack. The element with index 0 is the name of any currently-executing shell function. The bottom-most element (the one with the highest index) is "main". This variable exists only when a shell function is executing. Assignments to FUNCNAME have no effect and return an error status. If FUNCNAME is unset, it loses its special properties, even if it is subsequently reset. This variable can be used with BASH_LINENO and BASH_SOURCE. Each element of FUNCNAME has corresponding elements in BASH_LINENO and BASH_SOURCE to describe the call stack. For instance, ${FUNCNAME[$i]} was called from the file ${BASH_SOURCE[$i+1]} at line number ${BASH_LINENO[$i]}. The caller builtin displays the current call stack using this information.

[来源:Bash手册]

由于一些注释询问没有扩展名的文件名,这里有一个示例如何完成:

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

享受吧!

在bash中,您可以使用$0获取脚本文件名。通常$1,$2等用于访问CLI参数。类似地,$0是访问触发脚本的名称(脚本文件名)。

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

如果你使用/path/to/script.sh这样的路径调用脚本,那么$0也会给出带有路径的文件名。在这种情况下,需要使用$(basename $0)来获取脚本文件名。

在所有情况下获取脚本或源脚本的“真实路径”:

fullname=$(readlink $0)  # Take care of  symbolic links
dirname=${fullname%/*}       # Get (most of the time) the dirname
realpath=$(dirname $BASH_SOURCE) # TO handle sourced scripts
[ "$realpath" = '.' ] && realpath=${dirname:-.}

下面是要生成的bash脚本(在新创建的“workdir”子目录中,在当前目录的“mytest”中),该bash脚本将派生另一个脚本,该脚本将调用bash定义的函数....测试了许多方法来启动它们:

#!/bin/bash
##############################################################

ret=0

fullname=$(readlink $0)  # Take care of  symbolic links
dirname=${fullname%/*}       # Get (most of the time) the dirname
realpath=$(dirname $BASH_SOURCE) # TO handle sourced scripts
[ "$realpath" = '.' ] && realpath=${dirname:-.}

fullname_withoutextension=${fullname%.*}

mkdir -p workdir
cat <<'EOD' > workdir/_script_.sh
#!/bin/bash
##############################################################

ret=0

fullname=$(readlink $0)  # Take care of  symbolic links
dirname=${fullname%/*}       # Get (most of the time) the dirname
realpath=$(dirname $BASH_SOURCE) # TO handle sourced scripts
[ "$realpath" = '.' ] && realpath=${dirname:-.}

fullname_withoutextension=${fullname%.*}

echo
echo "# ------------- RESULTS ------------- #"
echo "# path to me (\$0)----------->  ${0}     "
echo "# arguments called with ---->  ${@}     "
echo "# \$1 ----------------------->  $1       "
echo "# \$2 ----------------------->  $2       "
echo "# path to me (\$fullname)---->  ${fullname} "
echo "# parent path(\${0%/*})------>  ${0%/*}  "
echo "# parent path(\$dirname)----->  ${dirname} "
echo "# my name ----\${0##*/}------>  ${0##*/} "
echo "# my source -\${BASH_SOURCE}->  ${BASH_SOURCE} "
echo "# parent path(from BASH_SOURCE) -> $(dirname $BASH_SOURCE)"
echo "# my function name -\${FUNCNAME[0]}------>  ${FUNCNAME[0]}"
echo "# my source or script real path (realpath)------------------>  $realpath"
echo
[ "$realpath" = "workdir" ] || ret=1
[ $ret = 0 ] || echo "*******************************************************"
[ $ret = 0 ] || echo "***********   ERROR  **********************************"
[ $ret = 0 ] || echo "*******************************************************"

show_params () {
        echo
        echo "# --- RESULTS FROM show_params() ---- #"
        echo "# path to me (\$0)----------->  ${0}     "
        echo "# arguments called with ---->  ${@}     "
        echo "# \$1 ----------------------->  $1       "
        echo "# \$2 ----------------------->  $2       "
        echo "# path to me (\$fullname)---->  ${fullname} "
        echo "# parent path(\${0%/*})------>  ${0%/*}  "
        echo "# parent path(\$dirname)----->  ${dirname} "
        echo "# my name ----\${0##*/}------>  ${0##*/} "
        echo "# my source -\${BASH_SOURCE}->  ${BASH_SOURCE} "
        echo "# parent path(from BASH_SOURCE) -> $(dirname $BASH_SOURCE)"
        echo "# my function name -\${FUNCNAME[0]}------>  ${FUNCNAME[0]}"
        echo "# my source or script real path (realpath)------------------>  $realpath"
        echo
        [ "$realpath" = "workdir" ] || ret=1
        [ $ret = 0 ] || echo "*******************************************************"
        [ $ret = 0 ] || echo "***********   ERROR  **********************************"
        [ $ret = 0 ] || echo "*******************************************************"

}
show_params "$@"

EOD

cat workdir/_script_.sh > workdir/_side_by_side_script_sourced.inc

cat <<'EOD' >> workdir/_script_.sh

echo "# . $realpath/_side_by_side_script_sourced.inc 'hello there' 'william'"
. $realpath/_side_by_side_script_sourced.inc 'hello there' 'william'

[ $ret = 0 ] || echo "*******************************************************"
[ $ret = 0 ] || echo "***********   ERROR  **********************************"
[ $ret = 0 ] || echo "*******************************************************"
EOD

chmod +x  workdir/_script_.sh
[ -L _mytest_ ] && rm _mytest_
ln -s workdir/_script_.sh _mytest_

# ------------- CALLED ------------- #

called_by () {
        echo '=========================================================================='
        echo " Called by : " "$@"
        echo '=========================================================================='
        eval "$@"
}

called_by bash _mytest_
called_by ./_mytest_

called_by bash workdir/_script_.sh
called_by workdir/_script_.sh
called_by . workdir/_script_.sh


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

echo
echo
[ $ret = 0 ] || echo "*******************************************************"
[ $ret = 0 ] || echo "***********   ERROR  **********************************"
[ $ret = 0 ] || echo "*******************************************************"
echo
[ $ret = 0 ] && echo ".... location of scripts (\$realpath) should always be equal to $realpath, for all test cases at date".
echo

# ------------- END ------------- #