如何在 Linux 上跟踪特定符号链接时“查找”?

如何在 Linux 上跟踪特定符号链接时“查找”?

我想要find文件(具有类似的查找功能),但跟随并且只跟随特定的符号链接(通过模式匹配)。

显然find它本身无法处理它:没有选项可以设置符号链接跟随行为;并且天真地find -L很容易锁定(或非常慢)。

答案1

问题的最后一句话表明,问题不在于一般的符号链接(例如,-newer在一种情况下应用于符号链接,而在另一种情况下应用于目标),而在于以下符号链接到目录从而下降到你不想要的地方。

规格find应检测无限循环,因此不应发生活锁。资源(包括时间)被浪费可能是一个问题,我理解您的担忧。

首先,使用-L允许find跟随您想要跟随的符号链接。然后您需要一种方法来检测其他符号链接。

Infind -L -type l永远不会为真,但您可以使用 检测符号链接-exec test -L {} \;(请记住-exec … \;,这也是一个测试,当且仅当内部命令以状态 0 退出时,它才会成功)。这样,您仍然可以对符号链接应用一些特定的测试,并-prune(或不)相应地应用。

例如以下命令将仅下降名称以 开头foo或以 结尾的符号链接bar

find -L . -exec test -L {} \; ! \( -name 'foo*' -o -name '*bar' \) -prune -o -print

无论你最初想要什么表达式,都将其放在 之后-prune -o。在上面的命令中,“原始”表达式是-print。请记住,-exec会抑制隐式-print,因此如果需要,-print请明确添加它(就像我们所做的那样)。

请注意,-name测试符号链接本身的名称。如果您想测试目标的名称,则需要realpath,可能basename还需要一些 shell 代码;例如:

find -L . -exec test -L {} \; -exec sh -c '
   case "$(basename "$(realpath "$1")")" in
      baz* ) exit 0 ;;
      *qux ) exit 1 ;;
   esac
   exit 0
' find-sh {} \; -prune -o -print

上述命令将-prune任何符号链接到名称以 开头的任何文件baz,但它将下降符号链接到名称以 结尾的目录qux(除非以 开头baz),最后是-prune所有其他符号链接。

笔记:

  • realpath并且basename不可移植。
  • realpath解析所有符号链接。
  • 符号链接损坏时的行为可能会或可能不会符合您的预期。
  • 为每个文件单独调用test会影响性能,但我找不到更好的方法。调用shrealpathbasename在这方面也很糟糕,但这里只发生在符号链接上,因此在大多数情况下影响是有限的。
  • find-sh解释如下:中的第二个 sh 是什么sh -c 'some shell code' sh
  • 在示例中,获取-pruned 的路径名将不会被-printed。将最后一段更改为-prune -false -o -print,它们将被打印出来。请参阅解释-false;如果您需要的话,还有一个便携式的替代品。

相关内容