Executando comandos consequentemente em várias pastas

2

Eu tenho a pasta pai "pai". Dentro dessa pasta eu tenho subpastas e um arquivo chamado "names.txt". este arquivo inclui os nomes dessas subpastas da seguinte forma:

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

O conteúdo do arquivo "names.txt" é o seguinte:

folder1
folder2
folder3
folder4
.
.
.

Dentro de cada pasta eu tenho imagens e eu quero aplicar consecutivamente 10 scripts em cada imagem (cada script deve terminar, é trabalho dentro de cada pasta, então o segundo script deve ser executado). 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 .Ao mesmo tempo, quero aplicar esse processo em todas as pastas de uma só vez. ou seja, quando o script # 1 estiver em execução, quero que ele esteja em execução em todas as pastas ao mesmo tempo. Quando isso for feito e o script # 2 será iniciado. Eu quero começar em todas as pastas de uma só vez e assim por diante ... Para conseguir isso eu escrevi o seguinte código:

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

done

Este código não está funcionando com eficiência, pois todos os comandos estão sendo executados de uma vez. Eu quero que os comandos sejam executados em todas as pastas de uma só vez, mas consecutivamente. O que estou fazendo errado?

    
por cas 08.07.2016 / 01:03

2 respostas

3

Primeiro, crie um script wrapper que mude para o diretório fornecido no primeiro (e único) argumento de linha de comando, execute o setup / variable-initialisation / etc de que ele precisa e execute seus 10 scripts em sequência com quaisquer args eles precisam.

Por exemplo, se cada script processa todos os arquivos .jpg, .png e .gif no diretório:

#! /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}

Em seguida, use find para enviar uma lista de diretórios para parallel .

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

(a opção -mindepth 1 em find exclui o diretório de nível superior, ou seja, o próprio diretório pai)

Por padrão, o paralelismo executará uma instância (um "trabalho") de ./example-wrapper.sh para cada núcleo da CPU que você possui. Cada instância receberá um nome de diretório ( -n 1 ). Assim que um trabalho termina, outro é iniciado (se houver algum trabalho restante para ser executado).

Isso maximiza o uso da energia disponível da CPU, sem permitir que as tarefas compitam entre si pelo tempo de CPU.

Você pode usar a opção parallel de -j para ajustar o número de tarefas a serem executadas de uma só vez. Para tarefas com uso intensivo de CPU, o padrão de um trabalho por núcleo do sistema é provavelmente o que você deseja.

Se seus trabalhos não exigem muito da CPU, mas tendem a ser mais E / S, você pode executar 2 ou 3 trabalhos para cada núcleo (dependendo do tamanho dos arquivos de entrada, da rapidez com que armazenamento é, e que tipo de dispositivos compõem esse armazenamento - por exemplo, os SSDs não sofrem de latência de busca, portanto, não serão retardados por vários processos que buscam dados de todo o disco. de ser feito para procurar aleatoriamente em todo o lugar - o armazenamento em buffer / armazenamento em cache do Linux ajudará, mas não eliminará o problema).

Se você deseja executar outro trabalho (por exemplo, uso normal da área de trabalho) enquanto esses trabalhos estão em execução, use -j para informar parallel para usar um ou dois núcleos a menos do que o seu sistema (por exemplo, -j 6 em um Sistema de 8 núcleos).

NOTA: Ajustar os processos paralelos é uma boa arte e pode levar algumas experiências para obter os melhores resultados.

De qualquer forma, de man parallel :

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

Number of jobslots. Run up to N jobs in parallel. 0 means as many as possible. Default is 100% which will run one job per CPU core.

If --semaphore is set default is 1 thus making a mutex.

Este é um uso realmente básico e primitivo de parallel . Pode fazer muito mais. Veja a man page para detalhes.

BTW, xargs também tem uma opção -P para executar trabalhos em paralelo. Para um uso simples como esse, faz pouca diferença se você usa xargs -P ou parallel . Mas se seus requisitos forem mais complicados, use parallel .

parallel deve ser empacotado para a maioria das distribuições Linux, caso contrário, está disponível no link

    
por 09.07.2016 / 14:20
0

O '&' coloca seus sub-scripts em segundo plano, e é por isso que eles estão sendo executados ao mesmo tempo.

O que você provavelmente quer fazer é inverter seus loops:

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