我有一个非常大的档案,由非常小的文件组成,连接成一个文本文件,并带有“”分隔符。对于较小的档案,我将split
使用“”作为模式进行档案,然后处理生成的文件。然而,在这个存档中,此类文件的数量级约为一亿个——显然,对于将它们全部放入一个目录来说太多了。我创建了文件夹aa
、ab
等,以便尝试将它们移动到创建的目录中。但是,我遇到了问题。我尝试过的事情:
没有命令可以
split
对结果文件执行任何命令。所以我必须用手做。**
使用将文件移动到目录中find . -name "xaa*" -exec mv {} aa \+
不起作用,因为{}
不在行尾。用于反转源和目标的标志
-t
在我的 Unix 版本中不可用。find
我必须将into的输出通过管道传输xargs
,才能正常工作。
然而,这太慢了——文件的创建速度比它们的移动速度快得多。
我怀疑
xargs
一次处理的文件比使用\+
after 少find -exec
。我尝试添加一个“-R 6000”标志,以便一次运行 6000 个条目;但是,我认为这没有什么区别。我将 的优先级降低
split
到尽可能低。它消耗的 CPU 量没有变化,所以可能也没有影响。我打开最多七个命令提示符来运行
mv
命令(每个命令提示符最后四个字母)——但是,这仍然不够。我会打开更多,但是一旦系统达到七个,响应就太慢了,我不得不停止分裂。例如,在等待ls -l | tail
命令返回某些内容时,源存档会被复制到 USB。
所以我一直在做的是,split
在此时停止,等待mv
命令赶上,然后重新启动分割。那时我会用来
find -exec rm {} \+
删除我已经拥有的文件;这有点快,所以当它到达我没有的文件时,周围的文件就会减少。
因此,第一次此类迭代持续了约 300 万个文件,下一个约 200 万个文件,下一个约 1.5 个文件。不过,我确信应该有更好的方法。还有什么想法可以尝试吗?
答案1
类似的东西xargs -I {} ... mv {} aa
仍然会mv
在每行输入中运行一次。从POSIX 规范-I
的选项xargs
:
Insert mode: utility is executed for each logical line from standard input.
您需要类似的东西xargs -r sh -c 'mv "$@" aa' _
(或者在那时,只是)来真正为多个文件find ... -exec sh -c 'mv "$@" aa' _ {} +
运行单个文件。mv
这样,您就可以使用 shell 在mv
目标目录之间插入参数。
"$@"
被 shell 替换为所有参数,没有任何字段分割或通配符。- 的作用与指定的脚本
_
相同。之后的参数将是、等,或者统称为。$0
sh -c
$1
$2
$@
即使这样,我认为你find
也会参与竞争条件。它可能会在split
结束之前完成目录列表的读取,因此可能无法处理所有文件。它还可能最终递归到您创建的子目录并检测之前移动到那里的文件,并且可能最终尝试再次移动aa/xaa
并aa/
出错(但是,-exec ... {} +
忽略命令的退出状态)。