我如何找到一个Bash脚本位于该脚本内部的目录的路径?
我想用Bash脚本作为另一个应用程序的启动器,我想将工作目录更改为Bash脚本所在的目录,所以我可以在该目录中的文件上运行,如下:
$ ./application
我如何找到一个Bash脚本位于该脚本内部的目录的路径?
我想用Bash脚本作为另一个应用程序的启动器,我想将工作目录更改为Bash脚本所在的目录,所以我可以在该目录中的文件上运行,如下:
$ ./application
当前回答
dirname ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}
如果您想跟随同步链接,请使用您上面的路径上的阅读链接,重复或非重复。
#
# Location: test1/test2/test_script.sh
#
echo $0
echo $_
echo ${BASH_SOURCE}
echo ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}
cur_file="${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
cur_dir="$(dirname "${cur_file}")"
source "${cur_dir}/func_def.sh"
function test_within_func_inside {
echo ${BASH_SOURCE}
echo ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}
}
echo "Testing within function inside"
test_within_func_inside
echo "Testing within function outside"
test_within_func_outside
#
# Location: test1/test2/func_def.sh
#
function test_within_func_outside {
echo ${BASH_SOURCE}
echo ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}
}
BASH - 来源
一个序列变量,其成员是源文件名,在 FUNCNAME序列变量中定义了相应的序列函数名称。
功能
这个变量可以使用 BASH_LINENO 和 BASH_SOURCE. FUNCNAME 的每个元素都有相应的元素在 BASH_LINENO 和 BASH_SOURCE 描述呼叫板. 例如, ${FUNCNAME[$i]} 被呼叫从文件 ${BASH_SOURCE[$i+1]} 到线号 ${BASH_LINENO[$i]}。
(源:Bash手册)
其他回答
您可以做到这一点,只需将脚本名称($0)与 realpath 和/或 dirname 相结合,它适用于 Bash 和 Shell。
#!/usr/bin/env bash
RELATIVE_PATH="${0}"
RELATIVE_DIR_PATH="$(dirname "${0}")"
FULL_DIR_PATH="$(realpath "${0}" | xargs dirname)"
FULL_PATH="$(realpath "${0}")"
echo "RELATIVE_PATH->${RELATIVE_PATH}<-"
echo "RELATIVE_DIR_PATH->${RELATIVE_DIR_PATH}<-"
echo "FULL_DIR_PATH->${FULL_DIR_PATH}<-"
echo "FULL_PATH->${FULL_PATH}<-"
结果将是这样的:
# RELATIVE_PATH->./bin/startup.sh<-
# RELATIVE_DIR_PATH->./bin<-
# FULL_DIR_PATH->/opt/my_app/bin<-
# FULL_PATH->/opt/my_app/bin/startup.sh<-
$0 是脚本本身的名称
4.4 特殊变量类型
例如:LozanoMatheus/get_script_paths.sh
我通常将以下列入我的脚本的顶部,这在大多数情况下工作:
[ "$(dirname $0)" = '.' ] && SOURCE_DIR=$(pwd) || SOURCE_DIR=$(dirname $0);
ls -l $0 | grep -q ^l && SOURCE_DIR=$(ls -l $0 | awk '{print $NF}');
第一行根据PWD的值指定源,如果从当前路径运行,或者如果从其他地方呼叫,则命名。
第二行检查路径,以确定它是否是一个同链接,如果是这样,更新 SOURCE_DIR 到链接本身的位置。
可能有更好的解决方案在那里,但这是我成功的最干净的。
在完整的披露中,......(我找到了这个使者的变量部分)以及在Rich’s sh的技巧中,我也在我自己的答案的披露下披露了他的页面的相关部分。
具体的:
雖然不是嚴格 POSIX 到目前為止, realpath 是一個 GNU 核心應用程式自 2012 年 全公開:我從未聽到它之前,我注意到它在 info coreutils TOC 和立即思考 [連結] 問題,但使用下列功能,如顯示應該可靠,(現在 POSIXLY?),我希望,有效地提供其呼叫者一個絕對來源的 $0:
% _abs_0() {
> o1="${1%%/*}"; ${o1:="${1}"}; ${o1:=`realpath -s "${1}"`}; eval "$1=\${o1}";
> }
% _abs_0 ${abs0:="${0}"} ; printf %s\\n "${abs0}"
/no/more/dots/in/your/path2.sh
另一方面,你可以这样做:
ps ww -fp $$ | grep -Eo '/[^:]*'"${0#*/}"
eval "abs0=${`ps ww -fp $$ | grep -Eo ' /'`#?}"
试试这:
func () {
body here
eval "$1=\${foo}"
}
foo='hello ; rm -rf /'
dest=bar
eval "$dest=$foo"
当然,下面的版本是完全安全的:
foo='hello ; rm -rf /'
dest=bar
eval "$dest=\$foo"
我会用这样的东西:
# Retrieve the full pathname of the called script
scriptPath=$(which $0)
# Check whether the path is a link or not
if [ -L $scriptPath ]; then
# It is a link then retrieve the target path and get the directory name
sourceDir=$(dirname $(readlink -f $scriptPath))
else
# Otherwise just get the directory name of the script path
sourceDir=$(dirname $scriptPath)
fi
这些其他答案中没有一个为Finder在OS X中启动的Bash脚本工作。
SCRIPT_LOC="`ps -p $$ | sed /PID/d | sed s:.*/Network/:/Network/: |
sed s:.*/Volumes/:/Volumes/:`"
它不太好,但它完成了工作。