我正在尝试编写一个脚本,其目的是并行化在后台运行进程的执行(创建一些文件的程序),并且当 for 循环中的所有命令完成时,将执行一个额外的命令(即移动所有生成的命令)另一个文件夹中的文件)。这就是我目前得出的结论:
#!/bin/bash
for f in ./lqns/*.lqn
do
java -jar DiffLQN.jar $f &
done
mv ./lqns/*.csv csvs
并行性有效,但它们永远不会到达线路mv
,终端会等待并且不会返回。为什么它不回来?我该如何解决?
也许问题出&
在决赛上?因为它等待另一个命令但没有更多?即使添加mv
我认为可以解决问题的行......
答案1
如果 csv 文件是由 java 命令生成的,则这将失败,因为它将mv
在生成任何文件之前运行。由于所有 java 进程都发送到后台,因此循环几乎会立即完成,因此脚本继续执行,mv
找不到要移动的文件,因此不执行任何操作。
一个简单的解决方案是使用wait
.来自help wait
(在 bash shell 中):
$ help wait
wait: wait [-fn] [-p var] [id ...]
Wait for job completion and return exit status.
Waits for each process identified by an ID, which may be a process ID or a
job specification, and reports its termination status. If ID is not
given, waits for all currently active child processes, and the return
status is zero. If ID is a job specification, waits for all processes
in that job's pipeline.
这里的相关位是“如果未给出 ID,则等待所有当前活动的子进程”。这意味着您可以wait
在循环之后添加,这将使脚本等到所有子进程完成后再继续:
#!/bin/bash
for f in ./lqns/*.lqn
do
java -jar DiffLQN.jar "$f" &
done
wait
mv ./lqns/*.csv csvs
或者,您可以组合java
和mv
命令:
#!/bin/bash
for f in ./lqns/*.lqn
do
java -jar DiffLQN.jar "$f" && mv /lqns/*.csv csvs &
done
另一个可能更好的选择是使用 GNU parallel
(它应该位于您正在运行的任何操作系统的存储库中),这是一个专门为此类事情而设计的工具。有了它,你可以做到:
parallel java -jar DiffLQN.jar ::: ./lqns/*.lqn
mv ./lqns/*.csv csvs