在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 ...]
当前回答
Echo $(cd $(dirname file1);pwd - p)
其他回答
MacPorts和Homebrew提供了包含greadlink (GNU readlink)的coreutils包。这要归功于Michael Kallweitt在mackb.com上的帖子。
brew install coreutils
greadlink -f file.txt
一个简单的perl单行程序,几乎可以在任何地方工作,没有任何外部依赖:
perl -MCwd -e 'print Cwd::abs_path shift' ~/non-absolute/file
将解除对符号链接的引用。
脚本中的用法可能是这样的:
readlinkf(){ perl -MCwd -e 'print Cwd::abs_path shift' "$1";}
ABSPATH="$(readlinkf ./non-absolute/file)"
Readlink -f做两件事:
它沿着符号链接序列迭代,直到找到一个实际的文件。 它返回该文件的规范化名称。,它的绝对路径名。
如果您愿意,您可以构建一个shell脚本,使用普通readlink行为来实现相同的功能。举个例子。显然,你可以在自己的脚本中插入这个,你想调用readlink -f
#!/bin/sh
TARGET_FILE=$1
cd `dirname $TARGET_FILE`
TARGET_FILE=`basename $TARGET_FILE`
# Iterate down a (possible) chain of symlinks
while [ -L "$TARGET_FILE" ]
do
TARGET_FILE=`readlink $TARGET_FILE`
cd `dirname $TARGET_FILE`
TARGET_FILE=`basename $TARGET_FILE`
done
# Compute the canonicalized name by finding the physical path
# for the directory we're in and appending the target file.
PHYS_DIR=`pwd -P`
RESULT=$PHYS_DIR/$TARGET_FILE
echo $RESULT
注意,这并不包括任何错误处理。特别重要的是,它不检测符号链接循环。一种简单的方法是计算循环的次数,如果碰到一个不太可能的大数字(比如1000),就会失败。
edit使用pwd -P而不是$ pwd。
注意,这个脚本希望被称为。/script_name文件名,不使用-f,如果你想能够像GNU readlink一样使用-f文件名,将$1更改为$2。
我想,迟到总比不到好。我之所以特别开发它,是因为我的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"