我正在寻找优化这个 find 命令。我们必须将一堆(有时几乎一百万个)文件移动到一个目录中以进行进一步处理。我们正在寻找一种方法来提高此命令的速度,因为运行大量文件可能需要几个小时。问题是我们需要在移动文件之前至少保留 1 分钟的文件,因为我们不想移动那些可能仍在写入的文件。
find path -name *.cdr.xml -mmin +1 -exec mv {} /path
编辑:该命令作为 python 脚本的一部分运行,我们必须等待找到并移动所有文件,然后才能继续执行 python 脚本。
所有文件名都是 UUID。
答案1
通过使用仅会导致分叉一次的+
结尾,可以实现性能改进。-exec
find
-exec
而在 的情况下;
,-exec
每次都会为新的参数分叉。
所以你可以使用:
find path -type f -name '*.cdr.xml' -mmin +1 -exec mv -t /path {} +
如果有可能出现重复的文件名:
find path -type f -name '*.cdr.xml' -mmin +1 -exec mv -it /path {} +
或者
find path -type f -name '*.cdr.xml' -mmin +1 -exec mv --backup=numbered -t /path {} +
--backup=numbered
mv
如果目标中的文件名相同,则将导致文件的编号备份,而不是覆盖。
答案2
你可以看一下看门狗(https://github.com/gorakhargosh/watchdog/)为了将所有逻辑保留在 python 中,您可以监视目录并在一分钟后移动每个文件而不进行修改。
另一种解决方案是使用同步传输所有文件寻找输出而不是构造-执行。
一点解释:
find ... -exec ... \;
-> 这将为每个结果执行命令,这会增加很多开销并且非常慢。
find ... -exec ... +
-> 这将连接所有结果并仅执行一次命令,这非常快,但您可能会达到命令的 shell 字符限制(特别是对于数百万个文件)。
现在与同步:
find path -name *.cdr.xml -mmin +1 -print0 | rsync --remove-source-files -0 --files-from=- ${DESTINATION}
解释:
find ... -print0 |
-> 这会将所有 NULL 分隔的结果传递到管道,由另一端的 rsync 处理。
--remove-source-files
-> 这是不言自明的,就像mv
.
--files-from=-
-> 这将从管道读取标准输入
-0
-> 这将从管道中读取以 NULL 结尾的列表而不是行。
为什么 NULL?...为了加快一点速度,NULL 比新行占用更少的字节,将其增加到一百万,您可以节省一堆字节。