您可以使用-o 的短路行为排除单个路径(就像您已经对~/Desktop/testrm/.snapshot 所做的那样)。
但是,对于每个排除的路径,您还必须排除其所有父目录。否则,您将通过删除 a/b/ 或 a/ 和 rm -rf 来删除 a/b/c。
在以下脚本中,函数orParents 生成find 命令的一部分。示例:
find $(orParents a/b/c) ... 将运行
find -path a/b/c -o -path a/b -o -path a -o ...。
#! /usr/bin/env bash
orParents() {
p="$1"
while
printf -- '-path %q -o' "$p"
p=$(dirname "$p")
[ "$p" != . ]
do :; done
}
find ~/Desktop/testrm -mindepth 1 \
$(orParents "$ROOT_DIR/$DATA_DIR") -path ~/Desktop/testrm/.snapshot -o \
-mtime +2 -prune -exec rm -rf {} +
警告:您必须确保$ROOT_DIR/$DATA_DIR 不 以/ 结尾并且不 包含全局字符,例如*、? 和 []。
空格可以,因为printf %q 可以正确转义它们。但是,find -path 将其参数独立地解释为 glob 模式。我们可以做一个双引号机制。也许像printf %q "$(sed 's/[][*?\]/\\&/' <<< "$p")" 这样的东西,但我不太确定find -path 究竟是如何解释它的论点的。
或者,您可以编写一个脚本isParentOf 并执行...
find ... -exec isParentOf "$ROOT_DIR/$DATA_DIR" {} \; -o ...
... 排除 $ROOT_DIR/$DATA_DIR 及其所有父母。如果您不想将脚本文件添加到路径中,这可能更安全、更便携,但设置起来更慢且麻烦(find -exec bash -c ... 等)。