我在一个目录中有100个文件,并希望通过几个步骤处理每个文件,而step1非常耗时。所以伪代码就像:
for filename in ~/dir/*; do
run_step1 filename >${filename}.out &
done
for outfile in ~/dir/*.out; do
run_step2 outfile >${outfile}.result
done
我的问题是如何检查给定输入文件的step1是否完整。我以前在C#中使用threads.join,但不确定bash shell是否具有等价物。
答案 0 :(得分:4)
看起来你想要:
for filename in ~/dir/*
do
(
run_step1 $filename >${filename}.out
run_step2 ${filename}.out >${filename}.result
) &
done
wait
这会在单独的子shell中处理每个文件,在每个文件上运行第一步,然后执行步骤2,但并行处理多个文件。
关于您唯一需要担心的问题是确保您不要尝试并行运行太多进程。您可能需要考虑GNU parallel
。
你可能想写一个简单的脚本(也许是doit.sh
):
run_step1 "$1" > "$1.out"
run_step2 "$1.out" > "$1.result"
然后从parallel
调用该脚本,每次调用一个文件。
答案 1 :(得分:3)
试试这个:
declare -a PROCNUMS
ITERATOR=0
for filename in ~/dir/*; do
run_step1 filename >${filename}.out &
PROCNUMS[$ITERATOR]=$!
let "ITERATOR=ITERATOR+1"
done
ITERATOR=0
for outfile in ~/dir/*.out; do
wait ${PROCNUMS[$ITERATOR]}
run_step2 outfile >${outfile}.result
let "ITERATOR=ITERATOR+1"
done
这将使创建的进程数组按顺序等待它们,因为它们需要完成,而不是依赖于in和out文件之间存在1对1的关系而且目录不会更改它正在运行。
如果您希望假设每个文件都是独立的,那么现在也可以异步运行第二个循环。
我希望这会有所帮助,但如果您有任何疑问,请发表评论。
答案 2 :(得分:1)
The Bash builtin wait
可以等待特定后台作业或所有后台作业完成。简单的方法是在两个循环之间插入wait
。如果您想更具体,可以在第二个循环中直接wait PID
之前保存每个后台作业的PID和run_step2
。
答案 3 :(得分:0)
在执行step1的循环之后,您可以编写另一个执行fg
命令的循环,该命令将上一个进程移动到后台移动到前台。
您应该知道,如果某个流程已经完成,fg
可能会返回错误。
在使用fg
s循环后,您确定所有步骤1都已完成。