我想从三个不同的文件夹中查找包含和排除某些文件的文件。
文件夹 1:
- 路径:/var/www/app/var/log/
- 仅排除:file1.log 和 file2.log
文件夹 2:
- 路径:/var/log/web/log/
- 仅包含:error.log
文件夹 3:
- 路径:/var/log/service/log/
- 仅包括:app1.error.log 和 app2.error.log
在这种情况下,我该如何搜索来自三个不同文件夹的文件?
答案1
您可以使用 来实现这一点。阅读有关在排除和包含上下文中find
的 的一般用法:find
递归搜索具有排除和包含的文件。
您的问题涉及三条路径,每条路径都有不同的要求。可以在一次调用中指定多个起点find
并构建表达式(例如使用-path
),以便对不同的路径执行不同的测试。这是可能的,但相当麻烦。一种简单的方法是按顺序运行三个单独的 find 命令。
find /var/www/app/var/log ! -name file1.log ! -name file2.log
find /var/log/web/log -name error.log
find /var/log/service/log -name app1.error.log -o -name app2.error.log
笔记:
上述命令中的多个空格只是为了强调它们的结构和相似性。
你说“我想查找文件”。上述命令将查找文件包括目录类型的文件;特别是第一个命令将找到自己的起点(
…/log
)。要查找常规文件,您只需要-type f
。要查找非目录,您只需要! -type d
。如果
file1.log
或app1.error.log
属于目录类型,则不清楚“包含”或“排除”是指单独的目录还是指目录及其下面的所有内容。这可能不是问题,因为file1.log
这些很可能是设置中的常规文件。需要说明的是,上述每个命令都会遍历其起始点下的整个目录树。例如,如果
file1.log
是目录类型,则! -name file1.log
不会停止find
测试file1.log/foo
。要排除子树,您需要-prune
。find
递归工作。使 GNUfind
不进入子目录的最简单方法是-maxdepth 1
。非 GNU 实现可能不支持它。使用纯 POSIXfind
事情没那么简单。您已标记Ubuntu;Ubuntu 提供
find
开箱即用的 GNU,因此可以-maxdepth 1
自由使用。正确使用
-o
并不像你想象的那么简单。如果涉及符号链接,请阅读 中的
-H
和-L
选项man 1 find
。您可能想要使用其中之一。
考虑到所有这些,我可以制作第三个命令的示例变体,该命令或许更好地满足您的需求:
find /var/log/service/log/ -maxdepth 1 -type f \( -name app1.error.log -o -name app2.error.log \)
或者 POSIX-ly(为了让答案对一般观众更有用):
find /var/log/service/log/. \( -name . -o -prune \) -type f \( -name app1.error.log -o -name app2.error.log \)
后一个命令中起始点的最后一个部分以 结尾.
。这允许我们使用通用解决方案(我的意思是形式-name . -o -prune
不依赖于起始点路径的真正有意义的部分)。另一方面,find
将在每个路径名中包含/.
,您可能不想要这样。
运行三个find
而不是一个并不会阻止您将结果传送到单个目的地(例如xargs
):
{ find … ; find … ; find … ; } | xargs …
注意在 Ubuntu 中你可以执行find … -print0 | xargs -r0 …
。这是更加坚固,但find … -print | xargs …
不便携。