tro*_*skn 341 macos freebsd sh
在Linux上,该readlink实用程序接受一个-f跟随其他链接的选项.这似乎不适用于Mac和可能基于BSD的系统.相当于什么?
这是一些调试信息:
$ which readlink; readlink -f
/usr/bin/readlink
readlink: illegal option -f
usage: readlink [-n] [file ...]
Run Code Online (Sandbox Code Playgroud)
tom*_*jwu 411
MacPorts和Homebrew提供了一个包含(GNU readlink)的coreutils包greadlink.感谢Michael Kallweitt在mackb.com上的帖子.
brew install coreutils
greadlink -f file.txt
Run Code Online (Sandbox Code Playgroud)
Kei*_*ith 164
readlink -f 做两件事:
如果您愿意,您可以构建一个使用vanilla readlink行为的shell脚本来实现相同的功能.这是一个例子.显然你可以在自己想要调用的脚本中插入它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
Run Code Online (Sandbox Code Playgroud)
请注意,这不包括任何错误处理.特别重要的是,它不会检测符号链接周期.一个简单的方法是计算你循环的次数,如果你遇到一个不可思议的大数字,例如1000,就会失败.
编辑使用pwd -P而不是$PWD.
请注意,如果您希望能够像GNU readlink一样使用此脚本,则需要调用like ./script_name filename,no -f,change $1to .$2-f filename
Mil*_*les 43
您可能感兴趣realpath(3),或Python os.path.realpath.两者并不完全相同; C库调用要求存在中间路径组件,而Python版本则不存在.
$ pwd
/tmp/foo
$ ls -l
total 16
-rw-r--r-- 1 miles wheel 0 Jul 11 21:08 a
lrwxr-xr-x 1 miles wheel 1 Jul 11 20:49 b -> a
lrwxr-xr-x 1 miles wheel 1 Jul 11 20:49 c -> b
$ python -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' c
/private/tmp/foo/a
Run Code Online (Sandbox Code Playgroud)
我知道你说你喜欢比其他脚本语言更轻量级的东西,但是为了编译二进制文件是令人难以忍受的,你可以使用Python和ctypes(在Mac OS X 10.5上提供)来包装库调用:
#!/usr/bin/python
import ctypes, sys
libc = ctypes.CDLL('libc.dylib')
libc.realpath.restype = ctypes.c_char_p
libc.__error.restype = ctypes.POINTER(ctypes.c_int)
libc.strerror.restype = ctypes.c_char_p
def realpath(path):
buffer = ctypes.create_string_buffer(1024) # PATH_MAX
if libc.realpath(path, buffer):
return buffer.value
else:
errno = libc.__error().contents.value
raise OSError(errno, "%s: %s" % (libc.strerror(errno), buffer.value))
if __name__ == '__main__':
print realpath(sys.argv[1])
Run Code Online (Sandbox Code Playgroud)
具有讽刺意味的是,这个脚本的C版本应该更短.:)
Mic*_*pat 26
我讨厌继续使用另一个实现,但我需要a)一个可移植的纯shell实现,以及b)单元测试覆盖,因为像这样的边缘情况的数量是非平凡的.
在Github上查看我的项目以获取测试和完整代码.以下是实施的概要:
正如基思史密斯精明地指出的那样,readlink -f有两件事:1)递归地解析符号链接,以及2)规范化结果,因此:
realpath() {
canonicalize_path "$(resolve_symlinks "$1")"
}
Run Code Online (Sandbox Code Playgroud)
首先,符号链接解析器实现:
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
}
Run Code Online (Sandbox Code Playgroud)
请注意,这是完整实现的略微简化版本.完整的实现为符号链接周期添加了一个小的检查,并稍微按摩了输出.
最后,规范化路径的功能:
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")
}
Run Code Online (Sandbox Code Playgroud)
就是这样,或多或少.很简单,可以粘贴到您的脚本中,但是非常棘手,您可能会依赖任何没有针对您的用例进行单元测试的代码.
小智 24
greadlink是实现-f的gnu readlink.您也可以使用macports或其他人,我更喜欢自制软件.
Jin*_*nKo 21
perl中的一个简单的单行程,几乎可以在任何地方工作,没有任何外部依赖:
perl -MCwd -e 'print Cwd::abs_path shift' ~/non-absolute/file
Run Code Online (Sandbox Code Playgroud)
将解除引用符号链接.
脚本中的用法可能如下所示:
readlinkf(){ perl -MCwd -e 'print Cwd::abs_path shift' "$1";}
ABSPATH="$(readlinkf ./non-absolute/file)"
Run Code Online (Sandbox Code Playgroud)
Jam*_*mes 18
我制作了一个名为realpath的脚本,看起来有点像:
#!/usr/bin/env python
import os.sys
print os.path.realpath(sys.argv[1])
Run Code Online (Sandbox Code Playgroud)
Pee*_*ech 11
那这个呢?
function readlink() {
DIR="${1%/*}"
(cd "$DIR" && echo "$(pwd -P)")
}
Run Code Online (Sandbox Code Playgroud)
FreeBSD和OSX有一个stat源自NetBSD 的版本.
您可以使用格式开关调整输出(请参阅上面链接中的手册页).
% cd /service
% ls -tal
drwxr-xr-x 22 root wheel 27 Aug 25 10:41 ..
drwx------ 3 root wheel 8 Jun 30 13:59 .s6-svscan
drwxr-xr-x 3 root wheel 5 Jun 30 13:34 .
lrwxr-xr-x 1 root wheel 30 Dec 13 2013 clockspeed-adjust -> /var/service/clockspeed-adjust
lrwxr-xr-x 1 root wheel 29 Dec 13 2013 clockspeed-speed -> /var/service/clockspeed-speed
% stat -f%R clockspeed-adjust
/var/service/clockspeed-adjust
% stat -f%Y clockspeed-adjust
/var/service/clockspeed-adjust
Run Code Online (Sandbox Code Playgroud)
某些OS X版本stat 可能缺少-f%R格式选项.在这种情况下-stat -f%Y可能就足够了.该-f%Y选项将显示符号链接的目标,而-f%R显示与文件对应的绝对路径名.
编辑:
如果你能够使用Perl(Darwin/OS X安装了最近的版本perl),那么:
perl -MCwd=abs_path -le 'print abs_path readlink(shift);' linkedfile.txt
Run Code Online (Sandbox Code Playgroud)
将工作.
这是一个便携式shell函数,应该可以在任何 Bourne类似的shell中使用.它将解决相对路径标点符号"..或".和解除引用的符号链接.
如果由于某种原因你没有realpath(1)命令或readlink(1)这可能是别名.
which realpath || alias realpath='real_path'
Run Code Online (Sandbox Code Playgroud)
请享用:
real_path () {
OIFS=$IFS
IFS='/'
for I in $1
do
# Resolve relative path punctuation.
if [ "$I" = "." ] || [ -z "$I" ]
then continue
elif [ "$I" = ".." ]
then FOO="${FOO%%/${FOO##*/}}"
continue
else FOO="${FOO}/${I}"
fi
## Resolve symbolic links
if [ -h "$FOO" ]
then
IFS=$OIFS
set `ls -l "$FOO"`
while shift ;
do
if [ "$1" = "->" ]
then FOO=$2
shift $#
break
fi
done
IFS='/'
fi
done
IFS=$OIFS
echo "$FOO"
}
Run Code Online (Sandbox Code Playgroud)
另外,以防任何人对此感兴趣的是如何在100%纯shell代码中实现basename和dirname:
## http://www.opengroup.org/onlinepubs/000095399/functions/dirname.html
# the dir name excludes the least portion behind the last slash.
dir_name () {
echo "${1%/*}"
}
## http://www.opengroup.org/onlinepubs/000095399/functions/basename.html
# the base name excludes the greatest portion in front of the last slash.
base_name () {
echo "${1##*/}"
}
Run Code Online (Sandbox Code Playgroud)
您可以在我的google网站上找到此shell代码的更新版本:http://sites.google.com/site/jdisnard/realpath
编辑:此代码根据2子句(freeBSD样式)许可条款获得许可.可以通过以上链接到我的网站找到许可证的副本.
一种对我有用的懒惰方式,
$ brew install coreutils
$ ln -s /usr/local/bin/greadlink /usr/local/bin/readlink
$ which readlink
/usr/local/bin/readlink
/usr/bin/readlink
Run Code Online (Sandbox Code Playgroud)
解决这个问题并在Mac上安装Homebrew或FreeBSD时启用readlink功能的最简单方法是安装'coreutils'软件包.在某些Linux发行版和其他POSIX OS上也可能是必需的.
例如,在FreeBSD 11中,我通过调用安装:
# pkg install coreutils
在使用Homebrew的MacOS上,命令将是:
$ brew install coreutils
不确定为什么其他答案如此复杂,这就是它的全部内容.这些文件不在同一个地方,它们还没有安装.
执行
按照https://brew.sh/ 上的说明进行操作
brew install coreutils
您可以将别名放在 ~/.bashrc、~/.bash_profile 或任何您习惯保留 bash 别名的地方。我个人将我的保存在 ~/.bashrc 中
alias readlink=greadlink
您可以为其他 coreutils 创建类似的别名,例如 gmv、gdu、gdf 等。但请注意,mac 机器上的 GNU 行为可能会让其他习惯使用本机 coreutils 的人感到困惑,或者可能会在您的 mac 系统上以意想不到的方式运行。
解释
coreutils 是一个brew安装 GNU/Linux 核心实用程序的软件包,这些实用程序对应于它们的 Mac OSX 实现,以便您可以使用它们
您可能会在 mac osx 系统上发现程序或实用程序,它们看起来与 Linux coreutils(“核心实用程序”)相似,但它们在某些方面有所不同(例如具有不同的标志)。
这是因为这些工具的 Mac OSX 实现是不同的。要获得原始的 GNU/Linux 类行为,您可以coreutils通过brew包管理系统安装包。
这将安装相应的核心实用程序,前缀为g. 例如对于readlink,您会找到相应的greadlink程序。
为了readlink像 GNU readlink( greadlink) 实现一样执行,您可以在安装 coreutils 后创建一个简单的别名。
| 归档时间: |
|
| 查看次数: |
112606 次 |
| 最近记录: |