在Linux上,readlink实用程序接受附加链接后面的选项-f。这似乎不适用于Mac和基于BSD的系统。等价的是什么?

下面是一些调试信息:

$ which readlink; readlink -f
/usr/bin/readlink
readlink: illegal option -f
usage: readlink [-n] [file ...]

当前回答

开始更新

This is such a frequent problem that we have put together a Bash 4 library for free use (MIT License) called realpath-lib. This is designed to emulate readlink -f by default and includes two test suites to verify (1) that it works for a given unix system and (2) against readlink -f if installed (but this is not required). Additionally, it can be used to investigate, identify and unwind deep, broken symlinks and circular references, so it can be a useful tool for diagnosing deeply-nested physical or symbolic directory and file problems. It can be found at github.com or bitbucket.org.

最后更新

另一个非常紧凑和高效的解决方案,它只依赖于Bash:

function get_realpath() {

    [[ ! -f "$1" ]] && return 1 # failure : file does not exist.
    [[ -n "$no_symlinks" ]] && local pwdp='pwd -P' || local pwdp='pwd' # do symlinks.
    echo "$( cd "$( echo "${1%/*}" )" 2>/dev/null; $pwdp )"/"${1##*/}" # echo result.
    return 0 # success

}

这还包括一个环境设置no_symlinks,它提供了将符号链接解析到物理系统的能力。只要no_symlinks被设置为某个值,即no_symlinks='on',那么symlinks将被解析为物理系统。否则将应用它们(默认设置)。

这应该可以在任何提供Bash的系统上工作,并将返回一个与Bash兼容的退出代码用于测试。

其他回答

实现

安装酿造

按照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后创建一个简单的别名或符号链接。

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+,但如果旧版本仍然存在,则可以使其与旧版本一起工作。

Perl有一个readlink函数(例如,如何在Perl中复制符号链接?)这适用于大多数平台,包括OS X:

perl -e "print readlink '/path/to/link'"

例如:

$ mkdir -p a/b/c
$ ln -s a/b/c x
$ perl -e "print readlink 'x'"
a/b/c

一种适合我的偷懒方式,

$ brew install coreutils
$ ln -s /usr/local/bin/greadlink /usr/local/bin/readlink
$ which readlink
/usr/local/bin/readlink
/usr/bin/readlink