在Linux上,readlink实用程序接受附加链接后面的选项-f。这似乎不适用于Mac和基于BSD的系统。等价的是什么?
下面是一些调试信息:
$ which readlink; readlink -f
/usr/bin/readlink
readlink: illegal option -f
usage: readlink [-n] [file ...]
在Linux上,readlink实用程序接受附加链接后面的选项-f。这似乎不适用于Mac和基于BSD的系统。等价的是什么?
下面是一些调试信息:
$ which readlink; readlink -f
/usr/bin/readlink
readlink: illegal option -f
usage: readlink [-n] [file ...]
当前回答
一种适合我的偷懒方式,
$ brew install coreutils
$ ln -s /usr/local/bin/greadlink /usr/local/bin/readlink
$ which readlink
/usr/local/bin/readlink
/usr/bin/readlink
其他回答
实现
安装酿造
按照https://brew.sh/上的说明操作
安装coreutils包
酿造安装coreutils
创建别名或符号链接
3 a。创建一个别名(每个用户)
您可以将别名放在~/中。bashrc,(~ /。Bash_profile,或者任何您习惯保存bash别名的地方。我个人把我的文件保存在~/.bashrc中
别名指向= greadlink
3 b。创建一个符号链接(系统范围)
ln -s /usr/local/bin/greadlink /usr/local/bin/readlink(来源:Izana)
这将在/usr/local/bin中创建一个符号链接,同时保留原始的readlink二进制文件。它可以工作,因为搜索readlink将返回2个结果。但是/usr/local/bin中的第二个将优先。
例如,哪个readlink
要撤消此更改,只需取消link /usr/local/bin/readlink
额外的工具
您可以为其他coreutil创建类似的别名或符号链接,例如gmv、gdu、gdf等等。但是要注意,GNU在mac机器上的行为可能会让其他习惯使用本机coreutils的人感到困惑,或者在mac系统上可能会以意想不到的方式表现。
解释
coreutils是一个brew包,用于安装GNU/Linux核心实用程序,这些实用程序对应于Mac OSX实现,以便您可以使用它们
你可能会发现mac osx系统上的程序或实用程序看起来与Linux coreutils(“核心实用程序”)相似,但它们在某些方面有所不同(例如具有不同的标志)。
这是因为Mac OSX对这些工具的实现是不同的。要获得原始的类似GNU/ linux的行为,您可以通过brew包管理系统安装coreutils包。
这将安装相应的核心实用程序,前缀为g。例如,对于readlink,你将找到相应的greadlink程序。
为了使readlink执行起来像GNU readlink (greadlink)实现,您可以在安装coreutils后创建一个简单的别名或符号链接。
您可能既需要可移植的纯shell实现,也需要单元测试覆盖率,因为此类情况的边缘情况的数量非常多。
查看我的项目在Github上的测试和完整代码。下面是实现的概要:
正如Keith Smith敏锐地指出的那样,readlink -f做了两件事:1)递归地解析符号链接,2)规范化结果,因此:
realpath() {
canonicalize_path "$(resolve_symlinks "$1")"
}
首先,符号链接解析器实现:
resolve_symlinks() {
local dir_context path
path=$(readlink -- "$1")
if [ $? -eq 0 ]; then
dir_context=$(dirname -- "$1")
resolve_symlinks "$(_prepend_path_if_relative "$dir_context" "$path")"
else
printf '%s\n' "$1"
fi
}
_prepend_path_if_relative() {
case "$2" in
/* ) printf '%s\n' "$2" ;;
* ) printf '%s\n' "$1/$2" ;;
esac
}
请注意,这是完整实现的略微简化版本。完整的实现为符号链接循环添加了一个小检查,并对输出进行了一些处理。
最后,规范化路径的函数:
canonicalize_path() {
if [ -d "$1" ]; then
_canonicalize_dir_path "$1"
else
_canonicalize_file_path "$1"
fi
}
_canonicalize_dir_path() {
(cd "$1" 2>/dev/null && pwd -P)
}
_canonicalize_file_path() {
local dir file
dir=$(dirname -- "$1")
file=$(basename -- "$1")
(cd "$dir" 2>/dev/null && printf '%s/%s\n' "$(pwd -P)" "$file")
}
差不多就是这样。简单到可以粘贴到您的脚本中,但也非常棘手,如果您依赖于任何用例中没有单元测试的代码,那就太疯狂了。
POSIX兼容的readlink -f实现POSIX shell脚本
https://github.com/ko1nksm/readlinkf
这是POSIX兼容的(没有bashism)。它既不使用readlink也不使用realpath。我已经通过与GNU readlink -f进行比较验证了它是完全相同的(参见测试结果)。它具有错误处理和良好的性能。可以安全地从readlink -f中替换。许可证是CC0,因此您可以将其用于任何项目。
此代码用于bat -core项目。
# POSIX compliant version
readlinkf_posix() {
[ "${1:-}" ] || return 1
max_symlinks=40
CDPATH='' # to avoid changing to an unexpected directory
target=$1
[ -e "${target%/}" ] || target=${1%"${1##*[!/]}"} # trim trailing slashes
[ -d "${target:-/}" ] && target="$target/"
cd -P . 2>/dev/null || return 1
while [ "$max_symlinks" -ge 0 ] && max_symlinks=$((max_symlinks - 1)); do
if [ ! "$target" = "${target%/*}" ]; then
case $target in
/*) cd -P "${target%/*}/" 2>/dev/null || break ;;
*) cd -P "./${target%/*}" 2>/dev/null || break ;;
esac
target=${target##*/}
fi
if [ ! -L "$target" ]; then
target="${PWD%/}${target:+/}${target}"
printf '%s\n' "${target:-/}"
return 0
fi
# `ls -dl` format: "%s %u %s %s %u %s %s -> %s\n",
# <file mode>, <number of links>, <owner name>, <group name>,
# <size>, <date and time>, <pathname of link>, <contents of link>
# https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html
link=$(ls -dl -- "$target" 2>/dev/null) || break
target=${link#*" $target -> "}
done
return 1
}
请参考最新的代码。它可能有些固定。
readlink的路径在我的系统和你的系统之间是不同的。请尝试指定完整路径:
/西南/ sbin / readlink -f
这个呢?
function readlink() {
DIR="${1%/*}"
(cd "$DIR" && echo "$(pwd -P)")
}