如何在Bash中检测符号链接是否损坏?

61

我使用 find 命令并通过 [ \( -L $F \) ] 遍历结果来收集特定的符号链接。

我想知道在这种情况下是否有一种简单的方法来确定该链接是否已损坏(指向不存在的文件)。

以下是我的代码:

FILES=`find /target/ | grep -v '\.disabled$' | sort`

for F in $FILES; do
    if [ -L $F ]; then
        DO THINGS
    fi
done
8个回答

60
# test if symlink is broken (by seeing if it links to an existing file)
if [ ! -e "$F" ] ; then
    # code if the symlink is broken
fi

5
请注意,如果文件根本不存在,代码也将被执行。在使用find时可以直接使用,但在其他情况下(例如通配符),应该与-h组合以处理这种情况,例如[ -h "$F" -a ! -e "$F" ] - Calimo
3
使用这种方法,你并没有真正测试符号链接。 - Sridhar Sarnobat
@Calimo 没有任何区别。 - Melab
7
@Melab 错了,请在评论之前先测试你的假设:https://git.io/fx95w 这个回答是不正确的。 - hasufell
1
对我没用。我创建了一个链接,然后删除了目标文件,但检查仍然返回true。 - cisk
显示剩余2条评论

38

这应该输出无效的链接:

find /target/dir -type l ! -exec test -e {} \; -print

您还可以将操作链接到 find 命令上,例如删除损坏的链接:

find /target/dir -type l ! -exec test -e {} \; -exec rm {} \;

如果你实际上正在运行大量的代码,这种方法效果不佳。你有一个“if”解决方案吗? - Freedo
find -L foo -type l不是更好吗?从快速测试来看,它确实有效且更简单。当然,你的回答展示了find的更多功能,这是一件好事。免责声明:我从很早的时候就醒着,所以可能有些遗漏。 - undefined

11

如果符号链接原本指向一个文件或目录,但现在已经损坏,那么这将起作用。

if [[ -L "$strFile" ]] && [[ ! -a "$strFile" ]];then 
  echo "'$strFile' is a broken symlink"; 
fi

“-L $strFile” 不就足够了吗?从文档中可以看到:“[-L FILE ] 如果 FILE 存在且是符号链接,则为真。”(来源:http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html)。 - Sos
1
@Sosi 这在旧的 bash 版本中可能需要吗?2014 年和 2019 年,我甚至可能不再拥有那个版本 :) - Aquarius Power
没错!这是一个很好的观点!我没有注意到这个帖子已经很老了,现在我为挖掘它感到内疚。 - Sos
@Sosi 我认为没有问题,更新的应用程序版本的答案应该更好。 - Aquarius Power
4
我们希望测试符号链接是否正常工作,即使文件只是一个损坏的符号链接,使用-L选项也会返回真。 - Freedo

4

这将找到所有类型为“link”的文件,也会解析为类型“link”。即,一个损坏的符号链接

find /target -type l -xtype l

3
变量:find -L /target -type l - cdelacroix
“你不能有一个指向未损坏的符号链接的符号链接吗?” - Sridhar Sarnobat
GNU find-xtype 会一直解析符号链接到最后。如果符号链接是好的,它将始终解析为不是符号链接的内容。在 GNU find 和 BSD find 中使用 -L 同样如此。 - docwhat

2

如果您不介意遍历非损坏的目录符号链接,可以使用以下命令找到所有孤立的链接:

$ find -L /target -type l | while read -r file; do echo $file is orphaned; done

要查找所有未孤立的文件,请使用以下命令:

$ find -L /target ! -type l

1
但这会遵循非损坏的符号链接到目录,而这可能不是我们想要的。 - rafak
/target 可能是一个文件,这种情况下目录遍历不是一个问题。 - docwhat

1
在最近的版本中,bash(5.1.16)的test -e "$link"[[ -e "$link" ]]的行为与预期不符,无法识别链接是否损坏。
我建议使用readlink(1)来测试链接的存在性,方法如下:
if [[ ! -L "$link" ]]; then
    echo "Missing or not a symlink"
else
    readlink -q "$link"
    if [[ $? -ne 0 ]]; then
         echo "Broken"
    fi
fi

-1

以下命令有什么问题:

file $f | grep 'broken symbolic link'


3
它有几个问题:1)它遵循一个工作的符号链接,如果目标是一个文件,将读取内容以确定其类型;2)输出的措辞可能不是永远都一样的;3)如果运行系统的语言环境不是英语,则可能不会打印英文消息。要解决第一个问题,请添加“-h”标志,要解决第三个问题,请在前面加上“LANG=C”。您可以或不可以认为第二个问题是可以接受的风险。 - kbolino

-1
如果它被认定为符号链接,但是“不存在”,那么它就是一个损坏的链接。
if [[ -h $link && ! -e $link ]] ; then
    _info "$link is a BROKEN SYMLINK"
fi

参考资料


“-h” 被描述为 如果文件存在且是符号链接则为True。 如果“-h”为真,则“-e”为真。 - docwhat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接