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

Scripting 如何在Solaris上的find命令中排除完整目录路径列表,scripting,find,solaris,sh,Scripting,Find,Solaris,Sh,我特别需要使用脚本在Solaris中查找无主文件和目录,并且需要能够从查找中排除完整的目录路径,因为它们可能包含数千个无主文件(这很正常,因为它们是托管在其他服务器上的文件)。我甚至不希望find在这些目录中搜索,因为它会挂起服务器(cpu在很长一段时间内达到99%),因此在egrep中管道化查找结果以过滤掉这些目录不是一个选项 我知道我可以按名称排除一个或多个目录: find/-mount-local\(-type d-a\(-name dir1-o-name dir2-o dir3\)-pr

我特别需要使用脚本在Solaris中查找无主文件和目录,并且需要能够从查找中排除完整的目录路径,因为它们可能包含数千个无主文件(这很正常,因为它们是托管在其他服务器上的文件)。我甚至不希望find在这些目录中搜索,因为它会挂起服务器(cpu在很长一段时间内达到99%),因此在egrep中管道化查找结果以过滤掉这些目录不是一个选项

我知道我可以按名称排除一个或多个目录:

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

但是,这将在任何目录的目录结构中的任何位置匹配dir1和dir2,这根本不是我想要的

我希望能够阻止find在以下目录中搜索(例如):

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

/opt/somedir/dir1
/var/dir2
/home/user1/dir1
我曾尝试在-name参数中使用regex,但由于find仅将“name”与它找到的内容的basename匹配,因此我无法指定路径。不幸的是,Solaris的find不支持GNU find选项,例如-wholename或-path,所以我有点搞砸了

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

script.sh”/path/to/dir1、/path/to/dir2、/path/to/dir3“


在Solaris(5.8及更高版本)上,如何使用find和标准sh脚本(/bin/sh)实现这一点?

您不能通过完整路径与匹配文件,但可以通过inode匹配文件。因此,使用
ls-i
生成要修剪的索引节点列表,然后调用
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中,请参见
os.path
模块中的
walk
函数。

从“/”启动
find
是有问题的。脚本中的一个预处理步骤,它只获取顶级路径元素,即/opt、/var,然后在排除您不感兴趣的目录后,为这些目录运行find???只是个主意,祝你好运!如果你提出了自己的解决方案,请发帖,因为这是一个有趣的问题。如果你从/开始发帖的话,你可能会更加关注这一点。此脚本的目的是生成审核符合性结果,列出我们为客户机支持的服务器中的所有无主文件和目录,而不知道它们可能在哪里。我们肯定知道有些目录我们永远不想扫描(/proc、/dev、remotemounts等等),但我们总是需要扫描其他所有目录。我们考虑了很多关于使用包含列表而不是排除列表的问题,我们别无选择,只能使用排除选项,因为它涵盖了最未知的案例(仍在关注我?)。只是按照建议复制了unix.stackexchange.com上的帖子:rozcietrzewiacz在unix.stackexchange.com上发布的潜在答案:“由于find的实现不支持-path test,您可以使用
-exec test“{}”=“/path/to/exclude”\;-prune
。应将{}扩展为完整路径名。”。我测试了这个解决方案,虽然它需要更多的处理能力,但它仍然有效。例如,如果我在文件服务器上运行这个程序,我会担心增加的处理时间和增加的CPU使用率。。。我正在考虑答案。你对此有何看法?我们将对其进行测试,让你知道它是如何工作的。别担心,如果这一切顺利,我会欣然接受答案!效果很好!然而,出于我的目的,我将sed替换为awk:
exclude_dirs_inums=
ls-bdi$exclude_dirs 2>/dev/null | awk'{print$1}'| tr'\n'、'| sed-e's/、$/'| sed-e's/,/-o-inum/g',然后我用表达式填充的变量是
f_exclude__dirs=“(-inum$exclude-prune-o>。(很抱歉格式化,但是我的代码中有太多的反勾号…@YanickGirouard提示:使用
$(…)
。这不仅更容易与降价相协调,而且当您在替换命令中插入引号时,它还将使您免于麻烦。为了避免最后的
-o
,您似乎经历了很多障碍。将
-e'$s/-o/'
添加到
sed
的参数中会简单得多。谢谢Gilles。事实上,我很清楚这一点。我记不起何时何地,但我曾经在一些旧系统上使用$()和/bin/sh时遇到问题。它无法解析,因为sh的版本太旧了(实际上可能是Solaris 5.8。我更喜欢$()我也可以,通常使用bash,但是这个脚本必须可以移植到数百个系统上,有些已经有好几年的历史了。我必须用我所知道的东西,毫无例外地到处都能用。对不起,Gilles,我第一次错过了你评论的最后一部分。
-e'$s/-o/'
到底要做什么?不熟悉这个表单.修剪最后一个?不知道你可以在s前面使用匹配字符吗?
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