【问题标题】:Delete all broken symbolic links with a line?用一行删除所有损坏的符号链接?
【发布时间】:2026-01-07 11:30:01
【问题描述】:

对于给定的文件夹,我怎样才能删除其中所有损坏的链接?

我找到了this answer,它显示了如何删除一个损坏的链接,但我不能将它们放在一行中。有没有一种方法可以解决这个问题?

损坏的符号是指向不再存在的文件/文件夹的链接。

【问题讨论】:

  • 直接来自“man find”:` find -L /usr/ports/packages -type l -exec rm -- {} + 删除 /usr/ports/packages 中所有损坏的符号链接。`

标签: bash shell unix symlink


【解决方案1】:

这是删除当前目录中所有损坏的符号链接的 POSIX 方法,无需递归。它的工作原理是告诉find 遍历符号链接 (-L),但在每个目录或符号链接到此类处停止 (-prune)。

find -L . -name . -o -type d -prune -o -type l -exec rm {} +

您也可以使用 shell 循环。测试-L 匹配符号链接,-e 匹配现有文件(不包括损坏的符号链接)。

for x in * .[!.]* ..?*; do if [ -L "$x" ] && ! [ -e "$x" ]; then rm -- "$x"; fi; done

如果你想递归到子目录,这种技术是行不通的。使用 GNU find(在非嵌入式 Linux 和 Cygwin 上可以找到),您可以使用 -xtype 谓词来检测损坏的符号链接(-xtype 使用符号链接的目标类型,并报告 l 损坏的链接)。

find -xtype l -delete

POSIXly,您需要结合使用两个工具。您可以使用find -type l -exec … 对每个符号链接调用命令,并使用[ -e "$x" ] 测试该链接是否未损坏。

find . -type l -exec sh -c 'for x; do [ -e "$x" ] || rm "$x"; done' _ {} +

最简单的解决方案是使用 zsh。删除当前目录中所有损坏的符号链接:

rm -- *(-@D)

括号中的字符是glob qualifiers- 用于取消引用符号链接,@ 仅匹配符号链接(-@ 组合表示仅损坏的符号链接),D 匹配点文件。要递归到子目录,请这样做:

rm -- **/*(-@D)

【讨论】:

  • +1 非常酷的 zsh 示例和总体答案。但同样的问题:为什么是rm 而不是unlink?有没有rm不安全的情况?
  • 只是在看这个问题:unix.stackexchange.com/questions/34248/… 和关于“find -L”的注意事项——不确定它是否适用,也没有时间去追它,但有人可能想要考虑在这里调查潜在的危险。
  • 另一种选择:find -L /path/to/check -type l -delete(来源:commandlinefu.com/commands/view/2369/…
  • 为什么这个find表达式不使用-maxdepth来防止递归?
  • @billycrook 哦,第一个。因为我提供的是 POSIX 解决方案,而 -maxdepth 不在 POSIX 中(但我认为它计划在 SUSv5 中)。
【解决方案2】:

基于您链接的答案的简单答案(对于给定目录,$DIR):

find -L $DIR -maxdepth 1 -type l -delete

【讨论】:

  • 我最喜欢这个。甚至 find 手册页似乎也暗示这是查找损坏的符号链接的解决方案。
  • 在 Mac OS (BSD find) 上,@sanmiguel 的命令出错:find: -delete: forbidden when symlinks are followed
  • 在 CentOS 中像魅力一样工作
  • @JDub9 这是看哪里和看那里时匹配的区别。 -L 是查看位置:包括符号链接目录的内容。 -type l 匹配什么:查找时找到的符号链接。
  • @jDub9 -L 告诉find 返回符号链接指向的文件的信息,或者如果它指向的文件不存在,则返回符号链接本身。 -type l 只返回符号链接的匹配项,它会立即过滤掉任何存在的链接目标,只留下指向不存在文件的符号链接。
【解决方案3】:

对于MAC,进行如下试运行:-

DIR=<some path>
find -L $DIR -maxdepth 1 -type l -print

现在,您可以按如下方式修剪旧的符号链接:-

for f in `find -L $DIR -maxdepth 1 -type l`; do unlink $f; done

【讨论】:

    【解决方案4】:

    来自man find 示例:

    find -L /usr/ports/packages -type l -exec rm -- {} +
    

    删除 /usr/ports/packages 中所有损坏的符号链接。

    【讨论】:

    • find -L /usr/ports/packages -type l -print -delete
    【解决方案5】:

    根据问题"How can I find broken symlinks"接受的答案回答:

    find . -type l -! -exec test -e {} \; -print | xargs rm
    

    【讨论】:

      【解决方案6】:

      symlinks 软件包已预装在许多发行版(包括 Ubuntu 16.04 和 Fedora 25)中,并具有一些非常有用的功能,其中之一正是您所寻找的:

      symlinks -d ./
      
          -d == delete dangling links
      

      【讨论】:

      • 符号链接未预装在 CentOS 7.3 或 Ubuntu 14 上。Ubuntu 16 的内核 4.10 存在此问题:groups.google.com/forum/#!topic/linux.kernel/C1Uk5cnrPgs。当然,如果你没有运行 SSL 服务器,那么 Ubuntu 16 可能就可以了。
      • 也可以在 Mac OS X 上使用:sudo port install symlinks
      【解决方案7】:

      您可以使用readlink 来确定符号链接是否损坏。

      以下将列出给定目录(和子目录)中所有损坏的符号链接:

      find . -type l -exec sh -c 'readlink -f "{}" 1>/dev/null || echo "{}"' -- "{}" \;
      

      echo 替换为rm 以摆脱损坏的那些!

      (我已将readlink 的输出重定向到/dev/null 以避免混淆;它会列出符号链接的目标。)

      【讨论】:

      • 你的昵称,我看到你喜欢重定向到 /dev/null :-) 谢谢,unlink 呢?
      • @fotanus 为什么unlinkrm 有什么问题?
      • @fotanus BTW,如前所述,在这种情况下重定向到 /dev/null 纯粹是为了避免混淆。即使不这样做,将echo替换为rm,也不会产生任何副作用。
      • 不确定.. 因为它是一个链接? :P 我知道它只会删除入口点,但并不比 rm 更安全?
      • 您似乎误解了unlink 的作用。它还会删除文件。然而,unlink,正如 POSIX 一样,应该只调用系统调用unlink 而不会做任何其他事情,而rm 有更多选项并且可以做其他事情,例如以交互方式询问确认删除。见this
      【解决方案8】:

      您可以尝试使用rmlint

      首先,将目录更改为包含损坏符号链接的文件夹,然后 运行以下命令查找指向无处的坏符号链接

      rmlint --types="badlinks"
      

      然后rmlint 将在您的当前目录中创建一个 bash 脚本rmlint.sh 并在您的终端中打印一个错误符号链接列表。要删除当前目录中的所有错误符号链接,您可以运行

      ./rmlint.sh
      

      不完全是一种衬里,但它非常易于使用。

      【讨论】:

        最近更新 更多