对多个文件夹连续执行命令

对多个文件夹连续执行命令

我有父文件夹“parent”。在这个文件夹中,我有子文件夹和一个名为“names.txt”的文件。该文件包含这些子文件夹的名称,如下所示:

Parent_folder
folder1
folder2
folder3
folder4
.
.
.
.
names.txt

文件“names.txt”的内容如下:

folder1
folder2
folder3
folder4
.
.
.

在每个文件夹中我都有图像,并且我想在每个图像上连续应用 10 个脚本(每个脚本必须在每个文件夹中完成它的工作,然后必须运行第二个脚本)。These scripts have different names and they are exist in one folder. I set an environment by sourcing a file then I can call these scripts by its name from terminal.同时,我想立即对所有文件夹应用此过程。即当脚本 #1 运行时,我希望它同时在所有文件夹上运行。完成后,脚本 #2 将启动。我希望它立即在所有文件夹中启动等等......为了实现这一点,我编写了以下代码:

#!/bin/bash
path=PATH/TO/THE/PARENT/FOLDER
for i in $(cat $path/names.txt); do
{
script#1
} &
{
script#2
} &
.
.
.

done

该代码无法有效运行,因为所有命令都同时运行。我希望命令同时在所有文件夹上连续运行。我做错了什么?

答案1

首先,创建一个包装器脚本,该脚本更改为第一个(也是唯一一个)命令行参数中给出的目录,执行它需要的任何设置/变量初始化/等,然后使用它们需要的任何参数按顺序运行 10 个脚本。

例如,如果每个脚本处理目录中的所有 .jpg、.png 和 .gif 文件:

#! /bin/bash
# example-wrapper.sh

cd "$1"

script1 *.{jpg,png,gif}
script2 *.{jpg,png,gif}
script3 *.{jpg,png,gif}
script4 *.{jpg,png,gif}
script5 *.{jpg,png,gif}
script6 *.{jpg,png,gif}
script7 *.{jpg,png,gif}
script8 *.{jpg,png,gif}
script9 *.{jpg,png,gif}
script10 *.{jpg,png,gif}

接下来,使用find管道将目录列表传输到parallel.

find /path/to/parent/ -mindepth 1 -type -d -print0 | 
  parallel -0 -n 1 ./example-wrapper.sh

-mindepth 1中的选项find不包括顶级目录,即父目录本身)

./example-wrapper.sh默认情况下,并行将为您拥有的每个 CPU 核心运行一个实例(一项“作业”) 。每个实例将获得一个 ( -n 1) 目录名称。一旦一个作业完成,另一个作业就会开始(如果还有任何剩余作业要运行)。

这可以最大限度地利用可用的 CPU 能力,而不会让作业相互竞争 CPU 时间。

您可以使用parallel-j选项来调整一次运行的作业数量。对于 CPU 密集型任务,每个系统核心一个作业的默认设置可能就是您想要的。

如果您的作业不是 CPU 密集型的,但往往更受 I/O 限制,您可能需要为您拥有的每个核心运行 2 或 3 个作业(取决于您的输入文件有多大、存储速度有多快、以及构成该存储的设备类型 - 例如,SSD 不会受到寻道延迟的影响,因此不会因从整个磁盘查找数据的多个进程而减慢硬盘的速度,并且会因寻道时间而减慢。随机地到处寻找——Linux 的磁盘缓冲/缓存会有所帮助,但不会消除问题)。

如果您想在这些作业运行时完成其他工作(例如正常的桌面使用),请使用-j告诉parallel您使用比您的系统少一两个的内核(例如-j 6在 8 核系统上)。

注意:调整并行进程是一门艺术,需要进行一些实验才能获得最佳结果。

无论如何,从man parallel

--jobs N, -j N, --max-procs N, -P N

职位数量。并行运行最多 N 个作业。 0 表示尽可能多。默认值为 100%,即每个 CPU 核心运行一个作业。

如果--semaphore设置默认值为 1,则创建互斥锁。

这确实是 的基本和原始用法parallel。它可以做更多事情。有关详细信息,请参阅手册页。

顺便说一句,xargs还可以-P选择并行运行作业。对于像这样的简单用法,使用xargs -P或没有什么区别parallel。但如果您的要求更复杂,请使用parallel.

parallel应该为大多数 Linux 发行版打包,否则可以从https://www.gnu.org/software/parallel/

答案2

“&”将您的子脚本置于后台,这就是它们同时运行的原因。

您可能想要做的是反转循环:

for script in script1 script2 script3 …; do
    for folder in $(cat $path/names.txt); do
        ( cd $path/$folder; $script; ) &
    done
    wait
done

相关内容