仅找到符号链接的目的地


50

为了在shell脚本中使用,我正在寻找一种命令行方式来获取符号链接的目标。我到目前为止最接近的是stat -N src输出src -> dst。当然,我可以解析输出并获取dst,但是我想知道是否有某种直接获取目的地的方法。

Answers:


61

readlink如果可用,另一种选择是使用专门设计的命令。

例如

$ readlink -f `command -v php`
/usr/bin/php7.1

21
readlink -f如果您想知道最后一个符号链接目标,而不仅仅是一个目标,请使用。
scai 2012年

好点子!算了
nikitautiu 2012年

11
请注意,这-f是GNU的不可移植扩展readlink
bahamat 2012年

2
readlink何时不可用?谢谢。
tommy.carstensen

2
@ tommy.carstensen readlink(1)是在2003年添加到GNU coreutils的,因此,如今,您几乎可以依赖于所有使用coreutils的系统上。(参看git.savannah.gnu.org/cgit/coreutils.git/commit/src/...
约瑟普布罗兹罗丹

16

在Mac OS X和FreeBSD / NetBSD / etc上。它的:

stat -f %Y <filename>

更一般地说,我猜解决方案是(stat --printf =%N使用奇怪的引号):

ls -l b | sed -e 's/.* -> //'

例:

# ln -s a b
# stat -f %Y b
a

另一种方法是:

# find b -maxdepth 0 -printf %l
a#

最后一行由于没有换行而被整顿,但是如果您需要将结果放入变量中,就可以了,就像这样

# f=$(find b -maxdepth 0 -printf %l)
# echo $f
a

如果碰巧是目录,-maxdepth则需要使用来防止find下降到b目录中。


我完全略过了,stat --printf='%N\n'这正是我想要的,奇怪的引号不会打扰我,它们相同的引号rm和
ln-交互式

这显然是不可移植的,因为在Linux上,GNU coreutils的stat(1)具有不同的参数,并link -> dest在输出中打印出来。应该检查find(1)解决方案是否与GNU findutils一起使用...
Josip Rodin 2015年

请不要忘记引用变量的扩展名,echo $f当符号链接指向时肯定不会产生期望的结果/*(是可能的)
Camusensei

3

这可以通过使用GNU做到findfind src -prune -printf "%l\n"


1

可移植:除了使用启发式解析ls -l输出,或者使用 perl -le 'print readlink("some-file")'

有些系统具有readlink命令,有些系统具有-f获取绝对路径的选项。

stat作为stat/ lstat系统调用的包装器,命令有多种实现方式。GNU一个在这方面没有用,但是zsh的内置一个更是如此:

zmodload zsh/stat
stat +link the-link

仍然使用zsh,您可以使用:A修饰符(适用于变量扩展,历史记录扩展和遍历)获得文件的绝对路径(删除每个symlink组件):

~$ gstat -c %N b
`b' -> `a'
~$ var=b
~$ echo $var:A
/home/me/a
~$ echo b(:A)
/home/me/a
~$ echo ?(@:A)
/home/me/a

1

在没有readlink或没有stat命令但有Python 2.x的系统上,我使用的是简短脚本:

#!/usr/bin/env python

import os, sys

if __name__ == "__main__":
    src = sys.argv[1]
    target = os.readlink(src)
    if not os.path.isabs(target):
            target = os.path.abspath(os.path.join(os.path.dirname(src), target))
    print target

请注意,与readlink -f此不同的是,它可能仅遵循一级符号链接。


1

便携式纯Bash Realpath

bash_realpath() {
  # print the resolved path
  # @params
  # 1: the path to resolve
  # @return
  # &1: the resolved link path

  local path="${1}"
  while [[ -L ${path} && "$(ls -l "${path}")" =~ -\>\ (.*) ]]
  do
    path="${BASH_REMATCH[1]}"
  done
  echo "${path}"
}

0

realpathcoreutils包装命令

readlink命令手册页中所链接。


例如:

realpath /bin/python

输出

/usr/bin/python2.7

在我的机器上。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.