$0和dirname $0无法获取脚本真实绝对路径,必须用readlink -f "$0"或cd "$(dirname "$0")" && pwd -p;前者简洁但macos/alpine不支持,后者兼容性强;均需双引号防空格错误,且不适用于source调用场景。

直接用 $0 或 dirname $0 得到的几乎总是相对路径或符号链接路径,不是脚本真实存放位置。要拿到**真正、稳定、可跨环境**的绝对路径,得靠组合命令处理路径解析和符号链接展开。
最推荐:readlink -f(主流 Linux 环境)
这是目前最简洁可靠的方案,一步到位获取脚本文件的真实绝对路径:
-
SCRIPT_PATH=$(readlink -f "$0")→ 脚本完整绝对路径(含文件名) -
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")→ 脚本所在目录的绝对路径 - 必须用双引号包裹
"$0",防止路径含空格或特殊字符时出错 - 注意:
readlink -f在 macOS 或 Alpine(BusyBox)中不可用;macOS 需装greadlink(brew install coreutils),Alpine 可改用纯 Bash 方案
兼容性更强:cd + pwd 组合(无依赖,全平台可用)
不依赖外部命令,适合容器、嵌入式或老旧系统:
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd -P)-
pwd -P表示“物理路径”,会自动解析并跳过所有符号链接 -
cd "$(dirname "$0")"先切换到脚本所在目录(哪怕$0是../bin/run.sh也能正确进入) - 该方式会临时改变当前工作目录,但因在子 shell 中执行(
$(...)),不影响脚本主流程
常见误区与失效场景
以下写法看似简单,实际在多数生产环境中会出错:
-
dirname $0→ 返回.、..、/usr/bin(如果是软链接)等非绝对路径 -
pwd→ 返回的是**当前工作目录**,不是脚本位置(比如你在/home下运行/opt/app/start.sh,pwd输出是/home) -
dirname $0; pwd(未用$(...)包裹)→ 两步分离执行,pwd拿到的是原始工作目录,不是dirname切换后的目录 - 没加双引号:
dirname $0遇到含空格路径(如/path/to/my script.sh)会报错或截断
补充说明:什么情况下这些方法会失效?
它们都基于脚本被 bash script.sh 或 ./script.sh 这类方式**直接执行**。如果脚本是被 source script.sh 加载的,$0 就变成当前 shell 名(如 -bash),此时所有方案都会失败——这种场景需另作判断或避免依赖 $0。











