我想要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
会影响性能,但我找不到更好的方法。调用sh
,realpath
和basename
在这方面也很糟糕,但这里只发生在符号链接上,因此在大多数情况下影响是有限的。 find-sh
解释如下:中的第二个 sh 是什么sh -c 'some shell code' sh
?- 在示例中,获取
-prune
d 的路径名将不会被-print
ed。将最后一段更改为-prune -false -o -print
,它们将被打印出来。请参阅解释-false
;如果您需要的话,还有一个便携式的替代品。