我可以使用以下命令显示链接指向的目标文件ls -l
:
snowch$ ls -l /usr/local/bin/mvn
lrwxr-xr-x 1 snowch admin 29 12 Dec 08:58 /usr/local/bin/mvn -> ../Cellar/maven/3.2.3/bin/mvn
有没有一种方法可以显示更少的输出,而无需通过其他命令(例如 awk)进行管道传输?例如:
snowch$ ls ?? /usr/local/bin/mvn
/usr/local/bin/mvn -> ../Cellar/maven/3.2.3/bin/mvn
我在 OS X 10.9.5 上运行 3.2.53。几个命令的输出如下所示:
snowch$ ls -H /usr/local/bin/mvn
/usr/local/bin/mvn
snowch$ ls -L /usr/local/bin/mvn
/usr/local/bin/mvn
snowch$ file /usr/local/bin/mvn
/usr/local/bin/mvn: POSIX shell script text executable
snowch$ file -b /usr/local/bin/mvn
POSIX shell script text executable
答案1
ls
不幸的是,没有检索文件属性并以任意方式显示它们的选项。有些系统为此有单独的命令(例如 GNU 有一个stat
命令或 GNU 中的功能find
)。
在大多数现代系统上,对于大多数文件,这应该可以工作:
$ ln -s '/foo/bar -> baz' the-file
$ LC_ALL=C ls -ldn the-file | sed '
1s/^\([^[:blank:]]\{1,\}[[:blank:]]\{1,\}\)\{8\}//'
the-file -> /foo/bar -> baz
其工作原理是删除 输出第一行的前 8 个空白分隔字段ls -l
。这应该可以工作,除非系统上不显示 gid,或者当存在大量链接时前两个字段连接在一起。
使用 GNU stat
:
$ LC_ALL=C stat -c '%N' the-file
'the-file' -> '/foo/bar -> baz'
使用 GNU find
:
$ find the-file -prune \( -type l -printf '%p -> %l\n' -o -printf '%p\n' \)
the-file -> /foo/bar -> baz
对于 FreeBSD/OS/X 统计:
f=the-file
if [ -L "$f" ]; then
stat -f "%N -> %Y" -- "$f"
else
printf '%s\n' "$f"
fi
与zsh
统计:
zmodload zsh/stat
f=the-file
zstat -LH s -- "$f"
printf '%s\n' ${s[link]:-$f}
许多系统还有readlink
专门获取链接目标的命令:
f=the-file
if [ -L "$f" ]; then
printf '%s -> ' "$f"
readlink -- "$f"
else
printf '%s\n' "$f"
fi
答案2
使用file
命令。
[sreeraj@server ~]$ ls -l mytest
lrwxrwxrwx 1 sreeraj sreeraj 15 Dec 12 09:31 mytest -> /usr/sbin/httpd
[sreeraj@server ~]$ file mytest
mytest: symbolic link to `/usr/sbin/httpd'
或者
[sreeraj@server ~]$ file -b mytest
symbolic link to `/usr/sbin/httpd'
[sreeraj@server ~]$
另外,请阅读 的手册页ls
并检查选项-L
,-H
看看是否能满足您的要求。
答案3
ls
至少有 GNU(显然,tcsh
还有 的实现)您可以修改$LS_COLORS
环境变量以在您喜欢的位置插入分隔符(但是tcsh
的内置函数ls-F
不执行链接目标 - 仅链接标志)通常ls
根据该环境变量中存储的值插入任意不可打印的终端转义符,但是没有什么可以阻止我们插入任意其他内容。更多关于此这里。
例如:
LS_COLORS='ln=///\n:lc=:no=//:rc=:rs=:' \
\ls ~ -l --color=always |
sed '\|///|,\|//|!d;//d'
//
这会在每个列表的开头放置一个字符串(所以就在之前lrwcrwx
)以及///\n
任何链接的文件名之前的 。sed
然后过滤行范围 - 它将d
删除每个输入行,直到遇到它///
,然后从那里到下一个匹配的行将//
删除匹配的行//
。因此它只获取链接名称和链接目标 - 无论中间的字符如何。这是因为/
不能出现在文件名中 - 并且任何路径中的那些ls
可能打印只会单独出现。
看?
mkdir test; cd test
touch 'long
name' shortname
ln -s l* "$(printf %s.ln l*)"; ln -s s* shortname.ln
LS_COLORS='ln=///\n:lc=:no=//:rc=:rs=:' \
\ls -l --color=always | sed '\|///|,\|//|!d;//d'
...打印:
long
name.ln -> long
name
shortname.ln -> shortname
自己尝试一下。
答案4
[在 Linux/Bash 上]
我会这样做:
ls -l | sed -e"s/ \+/ /g" | cut -d' ' -f 9-
该sed
命令将多个空格折叠为单个空格;提取cut
第 9 个字段,其中字段分隔符是空格。
典型输出:
libboost_atomic.a
libboost_atomic.so -> libboost_atomic.so.1.57.0
libboost_atomic.so.1.57.0
...
libboost_wserialization.a
libboost_wserialization.so -> libboost_wserialization.so.1.57.0
libboost_wserialization.so.1.57.0
替代方案是:
ls -l | awk '{ print $9, $10, $11 }'
ls -l | awk '{ $1 = $2 = $3 = $4 = $5 = $6 = $7 = $8 = "" ; print }'
但这些都是不完美的:第一个可以输出尾随空格;第二个,前导空格。