Answers:
我强烈建议不使用find -L
的任务(见下文解释)。这是执行此操作的其他一些方法:
如果要使用“纯find
”方法,则应如下所示:
find . -xtype l
(xtype
是在取消引用的链接上执行的测试)find
,但可能并非在所有版本中都可用。但是,还有其他选择:
您还可以test -e
从以下find
命令中执行:
find . -type l ! -exec test -e {} \; -print
甚至有一些grep
技巧可能比更好(即更安全)find -L
,但与问题中提出的完全不一样(它将在整个输出行中晃动,包括文件名):
find . -type l -exec sh -c 'file -b "$1" | grep -q ^broken' sh {} \; -print
solo从commandlinefufind -L
引用的技巧看起来不错而且很hacky,但是它有一个非常危险的陷阱:遵循所有符号链接。考虑目录,其内容如下所示:
$ ls -l
total 0
lrwxrwxrwx 1 michal users 6 May 15 08:12 link_1 -> nonexistent1
lrwxrwxrwx 1 michal users 6 May 15 08:13 link_2 -> nonexistent2
lrwxrwxrwx 1 michal users 6 May 15 08:13 link_3 -> nonexistent3
lrwxrwxrwx 1 michal users 6 May 15 08:13 link_4 -> nonexistent4
lrwxrwxrwx 1 michal users 11 May 15 08:20 link_out -> /usr/share/
如果您find -L . -type l
在该目录中运行,则/usr/share/
还将搜索所有内容(这可能需要很长时间)1。对于find
“不受传出链接影响” 的命令,请不要使用-L
。
1这看起来/usr/share
有点不便(该命令将“花很长时间”遍历所有对象)–但可能会导致更严重的后果。例如,考虑chroot环境:它们可以存在于主文件系统的某些子目录中,并且包含指向绝对位置的符号链接。这些链接对于“外部”系统而言似乎是断开的,因为它们仅在您输入chroot后才指向正确的位置。我还记得,一些引导程序使用的符号链接/boot
仅在初始引导阶段(引导分区安装为)才有意义/
。
因此,如果您使用find -L
命令从看起来无害的目录中查找然后删除损坏的符号链接,甚至可能会破坏系统...
/proc/XXX/exe
链接是否断开。为此,请使用test -e "$(readlink /proc/XXX/exe)"
。
find . -xtype l
意思是“找到所有(最终)目标文件是符号链接的符号链接”。但是符号链接的最终目标不能是符号链接,否则我们仍然可以跟随该链接,它不是最终目标。由于没有这样的符号链接,我们可以将它们定义为其他符号链接,即损坏的符号链接。
l
,对我来说就不那么混乱了。
-L
黑客攻击,而是(通常)一味地删除损坏的符号链接。
正如rozcietrzewiacz所说,find -L
将搜索扩展到符号链接目录可能会产生意想不到的结果,因此并不是最佳方法。还没有人提到
find /path/to/search -xtype l
是更简洁,逻辑上相同的命令
find /path/to/search -type l -xtype l
到目前为止提出的解决方案都无法检测到循环符号链接,这是另一种破坏方式。 这个问题解决了可移植性。总而言之,查找损坏的符号链接(包括循环链接)的可移植方法是:
find /path/to/search -type l -exec test ! -e {} \; -print
有关更多详细信息,请参阅此问题或ynform.org。当然,所有这些的最终来源是findutils documentaton。
find -L
陷阱以及周期性链接。+1
-xtype
在POSIX没有指定,事实上,如果你看一下find(1)
在MacOS上有-type
,但不是 -xtype
。
我相信将-L
标志添加到您的命令将使您摆脱grep:
$ find -L . -type l
http://www.commandlinefu.com/commands/view/8260/find-broken-symlinks
从男人那里:
-L Cause the file information and file type (see stat(2)) returned
for each symbolic link to be those of the file referenced by the
link, not the link itself. If the referenced file does not exist,
the file information and type will be for the link itself.
如果您需要其他行为(无论链接是断开还是循环的),也可以将%Y与find配合使用:
$ touch a
$ ln -s a b # link to existing target
$ ln -s c d # link to non-existing target
$ ln -s e e # link to itself
$ find . -type l -exec test ! -e {} \; -printf '%Y %p\n' \
| while read type link; do
case "$type" in
N) echo "do something with broken link $link" ;;
L) echo "do something with cyclic link $link" ;;
esac
done
do something with broken link ./d
do something with cyclic link ./e
参考
find
不支持命令的人来说,还有另一个简写xtype
可以从中得出:find . type l -printf "%Y %p\n" | grep -w '^N'
。当安迪(Andy)在他的剧本中以相同(基本)的想法击败我时,我不愿意将其写为单独的答案。:)
这将在当前目录中打印出损坏的符号链接的名称。
for l in $(find . -type l); do cd $(dirname $l); if [ ! -e "$(readlink $(basename $l))" ]; then echo $l; fi; cd - > /dev/null; done
在Bash中工作。不了解其他外壳。
-type l
是多余的,因为-xtype l
它将-type l
在非链接上运行。所以find -xtype l
可能就是您所需要的。感谢您的这种方法。