在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 ...]
当前回答
来自@Keith Smith的回答给出了一个无限循环。
这是我的答案,我只在SunOS上使用(SunOS错过了很多POSIX和GNU命令)。
这是一个脚本文件,你必须把它放在你的$PATH目录之一:
#!/bin/sh
! (($#)) && echo -e "ERROR: readlink <link to analyze>" 1>&2 && exit 99
link="$1"
while [ -L "$link" ]; do
lastLink="$link"
link=$(/bin/ls -ldq "$link")
link="${link##* -> }"
link=$(realpath "$link")
[ "$link" == "$lastlink" ] && echo -e "ERROR: link loop detected on $link" 1>&2 && break
done
echo "$link"
其他回答
我想,迟到总比不到好。我之所以特别开发它,是因为我的Fedora脚本无法在Mac上运行。问题在于依赖关系和Bash。mac没有,或者如果有,它们通常在其他地方(另一条路径)。跨平台Bash脚本中的依赖路径操作在最好的情况下是令人头痛的,在最坏的情况下是存在安全风险的——因此最好尽可能避免使用它们。
下面的get_realpath()函数很简单,以bash为中心,不需要依赖关系。我只使用Bash内置的echo和cd。它也相当安全,因为在每个阶段都会测试所有内容,并返回错误条件。
如果您不想遵循符号链接,那么在脚本前面放置set -P,否则cd将默认解析符号链接。它已经用文件参数{absolute | relative | symlink | local}进行了测试,它返回文件的绝对路径。到目前为止,我们还没有遇到任何问题。
function get_realpath() {
if [[ -f "$1" ]]
then
# file *must* exist
if cd "$(echo "${1%/*}")" &>/dev/null
then
# file *may* not be local
# exception is ./file.ext
# try 'cd .; cd -;' *works!*
local tmppwd="$PWD"
cd - &>/dev/null
else
# file *must* be local
local tmppwd="$PWD"
fi
else
# file *cannot* exist
return 1 # failure
fi
# reassemble realpath
echo "$tmppwd"/"${1##*/}"
return 0 # success
}
您可以将此函数与其他函数get_dirname, get_filename, get_stemname和validate_path结合使用。这些可以在我们的GitHub存储库中以realpath-lib的形式找到(完全公开-这是我们的产品,但我们免费向社区提供,没有任何限制)。它也可以作为一种教学工具——它有很好的文档。
我们已经尽最大努力应用所谓的“现代Bash”实践,但Bash是一个很大的主题,我相信总会有改进的空间。它需要Bash 4+,但如果旧版本仍然存在,则可以使其与旧版本一起工作。
来自@Keith Smith的回答给出了一个无限循环。
这是我的答案,我只在SunOS上使用(SunOS错过了很多POSIX和GNU命令)。
这是一个脚本文件,你必须把它放在你的$PATH目录之一:
#!/bin/sh
! (($#)) && echo -e "ERROR: readlink <link to analyze>" 1>&2 && exit 99
link="$1"
while [ -L "$link" ]; do
lastLink="$link"
link=$(/bin/ls -ldq "$link")
link="${link##* -> }"
link=$(realpath "$link")
[ "$link" == "$lastlink" ] && echo -e "ERROR: link loop detected on $link" 1>&2 && break
done
echo "$link"
我为OS X编写了一个realpath实用程序,它可以提供与readlink -f相同的结果。
这里有一个例子:
(jalcazar@mac tmp)$ ls -l a
lrwxrwxrwx 1 jalcazar jalcazar 11 8月 25 19:29 a -> /etc/passwd
(jalcazar@mac tmp)$ realpath a
/etc/passwd
如果您正在使用MacPorts,可以使用以下命令安装:sudo port selfupdate && sudo port install realpath。
解决这个问题并在安装了Homebrew或FreeBSD的Mac上启用readlink功能的最简单方法是安装“coreutils”包。在某些Linux发行版和其他POSIX操作系统上可能也是必需的。
例如,在FreeBSD 11中,我通过调用:
# PKG安装coreutils
在使用Homebrew的MacOS上,命令将是:
$ brew install coreutils
不太确定为什么其他答案如此复杂,这就是它的全部。文件并没有在不同的地方,只是还没有安装。
我个人做了一个叫realpath的脚本,看起来有点像:
#!/usr/bin/env python
import os, sys
print(os.path.realpath(sys.argv[1]))