我如何找到一个Bash脚本位于该脚本内部的目录的路径?
我想用Bash脚本作为另一个应用程序的启动器,我想将工作目录更改为Bash脚本所在的目录,所以我可以在该目录中的文件上运行,如下:
$ ./application
我如何找到一个Bash脚本位于该脚本内部的目录的路径?
我想用Bash脚本作为另一个应用程序的启动器,我想将工作目录更改为Bash脚本所在的目录,所以我可以在该目录中的文件上运行,如下:
$ ./application
当前回答
尝试使用:
real=$(realpath "$(dirname "$0")")
其他回答
這是Linux的特點,但你可以使用:
SELF=$(readlink /proc/$$/fd/255)
关键部分是,我正在减少问题的范围:我禁止通过路径间接执行脚本(如 /bin/sh [脚本路径与路径组件有关])。
这可以被检测到,因为0美元将是一个相对的路径,不解决与当前文件夹有关的任何文件。我相信使用#!机制的直接执行总是导致绝对0美元,包括当脚本在路径上找到时。
我也要求在象征性链接链接链接的任何字符和字符只包含一个合理的字符子,特别是不是 \n, >, * 或?. 这对于字符逻辑来说是必要的。
#!/bin/sh
(
path="${0}"
while test -n "${path}"; do
# Make sure we have at least one slash and no leading dash.
expr "${path}" : / > /dev/null || path="./${path}"
# Filter out bad characters in the path name.
expr "${path}" : ".*[*?<>\\]" > /dev/null && exit 1
# Catch embedded new-lines and non-existing (or path-relative) files.
# $0 should always be absolute when scripts are invoked through "#!".
test "`ls -l -d "${path}" 2> /dev/null | wc -l`" -eq 1 || exit 1
# Change to the folder containing the file to resolve relative links.
folder=`expr "${path}" : "\(.*/\)[^/][^/]*/*$"` || exit 1
path=`expr "x\`ls -l -d "${path}"\`" : "[^>]* -> \(.*\)"`
cd "${folder}"
# If the last path was not a link then we are in the target folder.
test -n "${path}" || pwd
done
)
尝试一下这样的东西:
function get_realpath() {
if [[ -f "$1" ]]
then
# The file *must* exist
if cd "$(echo "${1%/*}")" &>/dev/null
then
# The file *may* not be local.
# The exception is ./file.ext
# tTry 'cd .; cd -;' *works!*
local tmppwd="$PWD"
cd - &>/dev/null
else
# file *must* be local
local tmppwd="$PWD"
fi
else
# The file *cannot* exist
return 1 # Failure
fi
# Reassemble realpath
echo "$tmppwd"/"${1##*/}"
return 0 # Success
}
function get_dirname(){
local realpath="$(get_realpath "$1")"
if (( $? )) # True when non-zero.
then
return $? # Failure
fi
echo "${realpath%/*}"
return 0 # Success
}
# Then from the top level:
get_dirname './script.sh'
# Or within a script:
get_dirname "$0"
# Can even test the outcome!
if (( $? )) # True when non-zero.
then
exit 1 # Failure
fi
這些功能和相關工具是我們的產品的一部分,已為社區提供免費,可以在GitHub找到作為 realpath-lib. 它是簡單的,清潔和良好的文档(很棒的學習),純粹的Bash,並沒有依賴。
source '/path/to/realpath-lib'
get_dirname "$0"
if (( $? )) # True when non-zero.
then
exit 1 # Failure
fi
在我看来,最合适的解决方案是:
"$( cd "$( echo "${BASH_SOURCE[0]%/*}" )"; pwd )"
使用 dirname、 readlink 和 basename 最终会导致兼容性问题,所以如果可能的话最好避免。
这是我唯一能以可靠的方式说的话:
SCRIPT_DIR=$(dirname $(cd "$(dirname "$BASH_SOURCE")"; pwd))