unixfind(1)
实用程序非常有用,它允许我针对符合特定规范的许多文件执行操作,例如
find /dump -type f -name '*.xml' -exec java -jar ProcessFile.jar {} \;
上述操作可能会在特定目录下的每个 XML 文件上运行脚本或工具。
假设我的脚本/程序占用大量 CPU 时间,并且我有 8 个处理器。一次最多处理 8 个文件就好了。
GNU make 允许使用-j
标志进行并行作业处理,但find
似乎没有这样的功能。有没有其他通用的作业调度方法可以解决这个问题?
答案1
xargs
使用-P
选项(进程数)。假设我想在 4-cpu 机器上压缩目录中的所有日志文件:
find . -name '*.log' -mtime +3 -print0 | xargs -0 -P 4 bzip2
您还可以说-n <number>
每个进程的最大工作单元数。假设我有 2500 个文件,我说:
find . -name '*.log' -mtime +3 -print0 | xargs -0 -n 500 -P 4 bzip2
这将启动 4 个bzip2
进程,每个进程处理 500 个文件,然后当第一个进程完成时,将启动另一个进程处理最后 500 个文件。
不确定为什么以前的答案使用xargs
和 make
,那里有两个并行引擎!
答案2
GNU并行也可以帮忙。
find /dump -type f -name '*.xml' | parallel -j8 java -jar ProcessFile.jar {}
请注意,如果没有参数-j8
,则parallel
默认为您机器上的核心数:-)
答案3
无需“修复” find
——利用make
其自身来处理并行性。
让你的进程创建一个日志文件或其他输出文件,然后使用如下 Makefile:
.SUFFIXES: .xml .out
.xml.out:
java -jar ProcessFile.jar $< 1> $@
并调用如下代码:
find /dump -type f -name '*.xml' | sed -e 's/\.xml$/.out/' | xargs make -j8
更好的是,如果您确保仅在 Java 进程成功完成后才创建输出文件,您可以利用make
依赖关系处理来确保下一次只有未处理的文件完成。
答案4
所有建议都使执行并行运行,但如果文件树足够大,瓶颈可能就在于 find 本身。我的一位同事写道洛卡作为并行搜索,当您的文件系统可以并行扫描时,它非常有用。如果您的文件系统位于单个 HDD 上,它可能没有帮助,但如果它是 raid 设备、SSD 或更好的分布式文件系统,它将大有帮助。
locar 将在多个目录上并行执行文件扫描,因此您将更快地获得文件列表,然后还可以将其与 xargs 或 parallel 结合起来并行运行。