如果我希望 find 命令在找到一定数量的匹配项后停止,我该怎么做?
背景是我在一个文件夹中有太多文件,我需要将它们随机放入单独的文件夹中,例如:
find -max-matches 1000 -exec mv {} /path/to/collection1 \+;
find -max-matches 1000 -exec mv {} /path/to/collection2 \+;
这可以find
单独做吗?如果不是,那么最简单的方法是什么?
如果我希望 find 命令在找到一定数量的匹配项后停止,我该怎么做?
背景是我在一个文件夹中有太多文件,我需要将它们随机放入单独的文件夹中,例如:
find -max-matches 1000 -exec mv {} /path/to/collection1 \+;
find -max-matches 1000 -exec mv {} /path/to/collection2 \+;
这可以find
单独做吗?如果不是,那么最简单的方法是什么?
您可以实施新的
find
使用测试-exec
:会将找到的前 1000 个文件移动到
/path/to/collection1
.这工作如下:
seq 1 1000
输出 1000 行,通过管道传输到find
;-exec read
读取一行,如果管道关闭则失败(当seq
' 的输出已被消耗时);-exec
成功,则-exec mv ...
执行移动。-exec ... +
像您期望的那样工作:read
每次迭代运行一次,但find
会累积匹配的文件并mv
尽可能少地调用。这依赖于基于执行命令的退出状态的
find
'成功或失败的事实:成功时,继续处理上面给出的操作(因为默认运算符是“and”),当它失败时,停止。-exec
read
find
find
如果您
find
支持该-quit
操作,则可以使用它来提高效率:没有它,
find
将测试每个文件,即使它只会保留 1000 个mv
.我假设它
read
可以作为外部命令使用,并为;实现POSIX 规范。read
如果不是这种情况,sh -c read
可以改用。在这两种情况下,find
都将为它检查的每个文件启动一个单独的进程。由于除了遍历目录树之外您并没有使用
find
太多,我建议您直接使用 shell 来执行此操作。请参阅两者zsh
及bash
以下的变体。使用
zsh
外壳globbing 模式
./**/*(-.D[1,1000])
将匹配当前目录中或下的所有常规文件(或此类文件的符号链接),然后返回其中的第一个 1000。将-.
匹配限制为常规文件或指向这些文件的符号链接,而D
行为类似于dotglob
(bash
匹配隐藏名称)。这是假设在调用时通过扩展通配模式生成的命令不会变得太大
mv
。以上是非常低效的,因为它会扩展每个集合的全局。因此,您可能希望将路径名存储在数组中,然后移动其中的切片:
在创建数组时将其随机化
pathnames
(您提到要移动随机文件):您可以在 中做类似的事情
bash
(除了您不能轻易地将 glob 匹配的结果打乱bash
,除了可能通过 提供结果shuf
,所以我会跳过那一点):我不认为它可以用 just 来完成
find
。你可以使用类似的东西:-print0
,-z
, 并-0
共同确保一切正常,即使文件名中有换行符。我认为,直接使用 find 是不可能的,但是您可以使用带有 head 和 xargs 的管道,例如:
这会将前 1000 个文件移动到 collection1。
Stephens 回答 264963 可能最适合我的用例,但是对于这个问题的用例有一个简单的解决方法,只有 find 和 head:
将在(至少在 CentOS 8 上)
-print
之前进行评估,并且当关闭管道时,管道到头将导致退出。-exec
find
head