我有一个非常具体的需求,需要使用脚本在 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
最后也是同样的情况。