如何在Shell脚本中跨Linux和macOS读取符号链接目标?
跨Linux和macOS的POSIX Shell脚本获取符号链接目标的可移植方法
有没有可移植的方法(至少支持Linux和macOS)在POSIX Shell脚本中获取符号链接的目标?
之前在一个旧程序里看到过这段代码:
ls -lad "bin" 2> /dev/null | awk '{ printf ("%s\n", $11) }'
但这种写法有个严重问题——如果用户名或组名包含空格,ls的输出列会错位,导致awk取到错误字段直接失效。而大家常想到的stat命令,在Linux和macOS上的参数选项并不一致,没法直接通用。
下面是几种靠谱的兼容方案:
1. 使用readlink(推荐)
readlink是专门处理符号链接的工具,在Linux和macOS上都默认预装,基础用法一致:
link_target=$(readlink "bin")
这个命令会直接输出符号链接bin指向的目标路径。如果需要解析嵌套符号链接(比如链接指向另一个链接,最终获取真实路径),可区分系统处理:
- Linux下用
readlink -f "bin"规范化路径 - macOS下若要实现相同效果,可通过brew安装GNU版本的readlink(
brew install coreutils)后使用greadlink -f "bin";不想额外安装工具的话,也可以用循环手动解析嵌套链接。
2. 兼容stat的分支写法
如果必须用stat,可以通过判断系统类型调用对应参数:
if [ "$(uname)" = "Darwin" ]; then # macOS系统:用stat -f "%Y"获取链接目标 link_target=$(stat -f "%Y" "bin") else # Linux系统:用stat -c "%L"获取链接目标 link_target=$(stat -c "%L" "bin") fi
这样就能在两种系统上都正确拿到符号链接的目标。
3. 绝对要避开的坑:不要用ls解析链接
用ls配合awk提取链接目标的写法完全不可靠,除了用户名/组名含空格的问题,ls的输出格式还可能受系统locale、用户自定义配置(比如颜色输出)影响,导致脚本在不同环境下行为不一致,属于Shell脚本的典型反模式,绝对要避免。
内容的提问来源于stack exchange,提问作者olebole
相关产品推荐
相关产品推荐

