仅使用`ls`显示源文件和目标链接文件


11

我可以显示链接指向的目标文件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

Answers:


7

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 stat:

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

stat -f "%N -> %Y" -- /usr/local/bin/mvn很棒。谢谢!
克里斯·斯诺

1
在旧的RHEL6系统上,stat是GNU coreutils 8.4,它是一个stat -c %N -- /usr/local/bin/mvn。要删除报价单,我必须将其发送到| perl -pe 's/['"'"'`]//g'
cfi

@cfi tr -d \'\`就足够了。请注意,RHEL系统将具有GNU find,您将可以通过它控制更多内容。
斯特凡Chazelas

5

使用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看看是否这就够了您的要求。


酷,每天学习新东西。

@Sree-非常感谢!我尝试过这些ls选项,但没有尝试过file。不幸的是,这两种方法似乎都不起作用:(
克里斯·

@SHC抱歉,我认为您在linux箱子里。请添加osx为您的标签之一。那也应该引起osx用户的注意。我已经编辑了帖子以添加标签,但是我没有足够的积分来立即显示修改。
2014年

@Sree-不用担心,对于造成的混乱,我们深表歉意。无论如何,我都赞成您的回答,因为当我回到Linux机器上时,它将很有用。
克里斯·斯诺

也许检查osx上的“ readlink”实用程序。
tonioc

2

ls至少使用GNU (并且显然tcsh是GNU 的实现),您可以修改$LS_COLORS环境变量以在所需的位置插入定界符(但是tcsh的内置ls-F函数不执行链接目标-仅执行链接标志通常ls插入任意不可打印的终端转义符基于存储在该环境var中的值,但是没有什么可以阻止我们插入任意其他内容。更多关于此这里

例如:

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

自己尝试。


您是否知道除了ls支持LS_COLORS该方式的现代GNU版本--color=always以及自变量之后的and选项之外的任何实现?如果在GNU系统上,为什么在可以使用find或时会使用复杂的东西stat?如果您做一些,那也可能行不通ln -s /// some-file
斯特凡Chazelas

@StephaneChezales- 至少表明它应该与bsd类似地工作ls。我记得几个月前在其他地方读过有关lss都倾向于接受诸如语法之类的termcap。ln -s ///事情的好处-但\0NUL也可以- -R递归地工作。至于原因-好吧,它很容易使用。在某些情况下比find- 容易,而且这里的话题似乎要多得多find。无论如何,没有太多的人考虑它,所以当我被提醒时,我会提到它。
mikeserv 2014年

请参见手册页那里的FreeBSD。如果要在FreeBSD上进行测试,可以在VM中使用实时CD,例如GhostBSD / mfsbsd。
斯特凡Chazelas

@StéphaneChazelas-不,我不需要测试-绝对是另外一种动物。如果您愿意看的话,该答案中的链接中也链接了gnu源。我不知道我在哪里读那本书?非常感谢您指出这一点,这是我乐于放弃的错误假设。香港专业教育学院编辑答案。
mikeserv 2014年

的最新版本tcsh具有ls-F内置支持LS_COLORS与某些GNU版本相同的方式的内建函数ls,但是ls -F如果您向其传递任何选项,它就会诉诸调用,因此除非您的系统上使用lsGNU ls,否则在这里将无法使用。
斯特凡Chazelas

-1

[在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 }'

但是,这些都不是完美的:第一个可以输出尾随空格;第二个可以输出尾随空格。第二,前导空格。


问题明确指出:“ ...无需通过另一个命令传递管道...”
杰夫·谢勒

@JeffSchaller:好点;我同意。但是,我希望这对于想要回答标题问题的人仍然有用(在描述中没有细节)。
Rhubbarb 2015年
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.