尝试以下简单的单行语句:
适用于所有 UNIX/OSX/Linux
dir=$(cd -P -- "$(dirname -- "$0")" && pwd -P)
重击
dir=$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)
注意:命令中使用双破折号 (--) 表示命令选项的结束,因此包含破折号或其他特殊字符的文件不会中断命令。
注意:在 Bash 中,使用 ${BASH_SOURCE[0]} 代替 $0,否则在获取它时路径可能会中断 (source/.)。
适用于 Linux、Mac 和其他 *BSD:
cd "$(dirname "$(realpath "$0")")";
注意:realpath 应默认安装在最流行的 Linux 发行版(如 Ubuntu)中,但在某些情况下可能会丢失,因此您必须安装它。
注意:如果您使用的是 Bash,请使用 ${BASH_SOURCE[0]} 而不是 $0,否则在获取它时路径可能会中断 (source/.)。
否则您可以尝试类似的方法(它将使用第一个现有工具):
cd "$(dirname "$(readlink -f "$0" || realpath "$0")")"
特定于 Linux:
cd "$(dirname "$(readlink -f "$0")")"
在 *BSD/Mac 上使用 GNU readlink:
cd "$(dirname "$(greadlink -f "$0")")"
注意:您需要安装coreutils
(例如1.安装Homebrew,2.brew install coreutils)。
在 bash 中
在 bash 中,您可以使用 Parameter Expansions 来实现,例如:
cd "${0%/*}"
但如果脚本从同一目录运行,则不起作用。
您也可以在 bash 中定义以下函数:
realpath () {
[[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}
这个函数有 1 个参数。如果参数已经有绝对路径,则按原样打印,否则打印$PWD变量+文件名参数(不带./前缀)。
或者这里是取自 Debian .bashrc 文件的版本:
function realpath()
{
f=$@
if [ -d "$f" ]; then
base=""
dir="$f"
else
base="/$(basename "$f")"
dir=$(dirname "$f")
fi
dir=$(cd "$dir" && /bin/pwd)
echo "$dir$base"
}
相关:
另见:
How can I get the behavior of GNU's readlink -f on a Mac?