如果我想在找到一定数量的匹配项后停止 find 命令,我该怎么做?
背景是我在一个文件夹中有太多文件,我需要将它们随机放入单独的文件夹中,例如:
find -max-matches 1000 -exec mv {} /path/to/collection1 \+;
find -max-matches 1000 -exec mv {} /path/to/collection2 \+;
Run Code Online (Sandbox Code Playgroud)
这可以find
单独做吗?如果不是,那么最简单的方法是什么?
Ste*_*itt 17
您可以实施新的测试以find
使用-exec
:
seq 1 1000 |
find . -exec read \; -exec mv {} /path/to/collection1 +
Run Code Online (Sandbox Code Playgroud)
将找到的前 1000 个文件移动到/path/to/collection1
.
其工作原理如下:
seq 1 1000
输出 1000 行,通过管道输入find
;-exec read
读取一行,如果管道关闭则失败(当seq
的输出被消耗时);-exec
成功,则-exec mv ...
执行移动。-exec ... +
如您所料:read
每次迭代运行一次,但find
会累积匹配的文件并mv
尽可能少地调用。
这取决于基于执行命令的退出状态find
's-exec
成功或失败的事实:read
成功时,find
继续处理上面给出的操作(因为默认运算符是“and”),失败时find
停止。
如果你find
支持这个-quit
动作,你可以用它来提高效率:
seq 1 1000 |
find . \( -exec read \; -o -quit \) -exec mv {} /path/to/collection1 +
Run Code Online (Sandbox Code Playgroud)
没有它,find
将测试每个文件,即使它只会保留 1000 个mv
.
我假设它read
可作为外部命令使用,并实现了 POSIX 规范read
;如果不是这种情况,sh -c read
可以改用。在这两种情况下,find
都会为它检查的每个文件启动一个单独的进程。
Kus*_*nda 17
由于您find
除了遍历目录树之外没有太多用途,因此我建议您直接使用 shell 来执行此操作。看到两者的变化zsh
和bash
下方。
使用zsh
外壳
mv ./**/*(-.D[1,1000]) /path/to/collection1 # move first 1000 files
mv ./**/*(-.D[1,1000]) /path/to/collection2 # move next 1000 files
Run Code Online (Sandbox Code Playgroud)
globbing 模式./**/*(-.D[1,1000])
将匹配当前目录中或当前目录下的所有常规文件(或此类文件的符号链接),然后首先返回其中的 1000。在-.
限制比赛进行到常规文件或符号链接到这些,而D
行为就像dotglob
在bash
(比赛隐藏的名字)。
这是假设在调用mv
.
以上是非常低效的,因为它会扩展每个集合的全局。因此,您可能希望将路径名存储在一个数组中,然后移动它的切片:
pathnames=( ./**/*(-.D) )
mv $pathnames[1,1000] /path/to/collection1
mv $pathnames[1001,2000] /path/to/collection2
Run Code Online (Sandbox Code Playgroud)
pathnames
在创建数组时随机化数组(您提到要移动随机文件):
pathnames=( ./**/*(-.Doe['REPLY=$RANDOM']) )
Run Code Online (Sandbox Code Playgroud)
您可以在 中做类似的事情bash
(除了您不能轻松地将 glob 匹配的结果改组bash
,除了可能通过 提供结果shuf
,所以我将跳过那一点):
shopt -s globstar dotglob nullglob
pathnames=()
for pathname in ./**/*; do
[[ -f $pathname ]] && pathnames+=( "$pathname" )
done
mv "${pathnames[@]:0:1000}" /path/to/collection1
mv "${pathnames[@]:1000:1000}" /path/to/collection2
mv "${pathnames[@]:2000:1000}" /path/to/collection3
Run Code Online (Sandbox Code Playgroud)
xen*_*oid 10
我不认为它可以只用find
. 您可以使用以下内容:
find [... your parameters ...] -print0 | head -z -1000 | xargs -0 mv -t /path/to/collection
Run Code Online (Sandbox Code Playgroud)
-print0
, -z
, 和-0
一起工作以确保即使文件名中有换行符也能正常工作。
归档时间: |
|
查看次数: |
2886 次 |
最近记录: |