如何在Bash for循环中限制并行处理哈希命名MP4文件的任务数?
问题描述
我有大约10000个以哈希值命名的MP4文件,需要对它们执行命令。同时处理约10个文件能提升效率,但由于文件名是哈希值,没有明确的迭代模式。
以下是逐个处理文件的顺序for循环:
顺序for循环:
src_dir='/path/to/src' dest_dir='/path/to/dest' for f in $src_dir/*.mp4 ; do echo $dest_dir/new_$(basename ${f}); done;
一次性启动所有命令的并行for循环:
src_dir='/path/to/src' dest_dir='/path/to/dest' for f in $src_dir/*.mp4 ; do echo $dest_dir/new_$(basename ${f}) & done;
请问是否有简单的方法,在for循环中限制同时启动的并行任务数量?
注:我了解parallel --link -j{num} {command}:::x y z可以指定同时启动的命令数,但不确定如何便捷地指定哈希文件名作为参数。
解决方案
方法1:使用parallel(推荐)
你提到的parallel工具可以直接批量传入文件路径,用-j参数指定并行任务数,并且内置了文件名处理的占位符,无需额外调用basename:
src_dir='/path/to/src' dest_dir='/path/to/dest' parallel -j 10 "echo ${dest_dir}/new_{/}" ::: ${src_dir}/*.mp4
-j 10:限制同时运行10个任务{/}:自动提取文件的basename(即去掉路径的纯文件名),和$(basename ${f})效果完全一致::: ${src_dir}/*.mp4:将目录下所有MP4文件作为参数批量传入
方法2:使用xargs
xargs的-P参数可以控制并行进程数,结合-I做占位符替换,也能实现需求:
src_dir='/path/to/src' dest_dir='/path/to/dest' find ${src_dir} -maxdepth 1 -name "*.mp4" | xargs -I {} -P 10 echo "${dest_dir}/new_$(basename {})"
或者直接读取文件列表的写法:
src_dir='/path/to/src' dest_dir='/path/to/dest' xargs -a <(ls ${src_dir}/*.mp4) -I {} -P 10 echo "${dest_dir}/new_$(basename {})"
-P 10:设置并行任务数为10-I {}:用{}作为文件名的占位符,替换到命令指定位置
方法3:手动在for循环中控制进程数
如果不想依赖外部工具,可以在原有for循环里添加计数和wait命令,手动控制并行数量:
src_dir='/path/to/src' dest_dir='/path/to/dest' max_jobs=10 count=0 for f in ${src_dir}/*.mp4; do echo "${dest_dir}/new_$(basename ${f})" & ((count++)) # 达到最大并行数时,等待所有后台进程完成再继续 if (( count >= max_jobs )); then wait count=0 fi done wait # 等待最后一批未完成的任务结束
wait:会阻塞当前脚本,直到所有后台进程执行完毕- 每启动
max_jobs个任务就触发一次等待,循环往复直到处理完所有文件
内容的提问来源于stack exchange,提问作者Zahra
相关产品推荐
相关产品推荐

