如何在 Solaris 上的 find 命令中排除完整目录路径列表

如何在 Solaris 上的 find 命令中排除完整目录路径列表

(从堆栈溢出复制:https://stackoverflow.com/questions/7854975/how-to-exclude-a-list-of-full-directory-paths-in-find-command-on-solaris

我有一个非常具体的需求,需要使用脚本在 Solaris 中查找无主文件和目录,并且需要能够从查找中排除完整目录路径,因为它们可能包含数千个无主文件(这很正常,因为它们是托管在其他文件上的文件)服务器)。我什至不想在这些目录中进行 find 搜索,因为它会挂起服务器(CPU 长时间飙升至 99%),因此在egrep 中通过管道传输 find 结果来过滤掉这些目录不是一个选项。

我知道我可以这样做来按名称排除多个目录之一:

find / -mount -local \( -type d -a \( -name dir1 -o -name dir2 -o dir3 \) \) -prune -o \( -nouser -o -nogroup \) -print

但是,这将匹配任何目录的目录结构中任何位置的 dir1 和 dir2,即不是我到底想要什么。

我希望能够阻止 find 甚至在以下目录中搜索(作为示例):

/opt/dir1
/opt/dir2
/var/dir3/dir4

我仍然希望它在以下目录中找到无主文件和目录:

/opt/somedir/dir1
/var/dir2
/home/user1/dir1

我尝试在 -name 参数中使用正则表达式,但由于 find 仅将“name”与它找到的基本名称相匹配,因此我无法指定路径。不幸的是,Solaris 的查找不支持 GNU 查找选项,例如 -wholename 或 -path,所以我有点搞砸了。

我的目标是拥有一个具有以下语法的脚本:

script.sh "/path/to/dir1,/path/to/dir2,/path/to/dir3"

我如何在 Solaris(5.8 及更高版本)上使用 find 和标准 sh 脚本 (/bin/sh) 来做到这一点?

答案1

您无法通过完整路径来匹配文件索拉里斯find,但您可以通过 inode 来匹配文件。因此,使用ls -i生成要修剪的 inode 列表,然后调用find.这假设您想要修剪的目录没有太多,以至于超出了命令行长度限制。

inode_matches=$(ls -bdi /opt/dir1 /opt/dir2 /var/dir3/dir4 |
                sed -e 's/ *\([0-9][0-9]*\) .*/-inum \1 -o/')
find / -xdev \( $inode_matches -nouser -o -nogroup \) -prune -o -print

另一种方法是使用 Perl 或 Python 脚本并进行您自己的目录遍历。 Perl 附带了一个find2perl脚本,可以帮助您开始使用该File::Find模块。在 Python 中,请参阅模块walk中的函数os.path

答案2

由于 find 的实现不支持-path测试,因此您可以使用-exec test "{}" = "/path/to/exclude" \; -prune{}应扩展为完整路径名)来模拟它。

不幸的是,这将比“纯粹”查找花费更多时间,因为test程序将在每次运行中执行。因此,请确保尽可能优化测试 - 例如,检查这两个中哪一个运行得更快:

 -exec test "{}" = "/dev" \; -o -exec test "{}" = "/proc" \; -o -exec test "{}" = "/tmp/test" \;

或者

 -exec test "{}" = "/dev" -o "{}" = "/proc" -o "{}" = "/tmp/test" \;

我认为后者总体来说应该更快,因为test程序只执行一次。

-a注意: and 逻辑不需要's;这是默认暗示的。-print最后也是同样的情况。

相关内容