Como executo o mesmo conjunto de comandos em vários subdiretórios, em ordem numérica?

3

Dentro do meu parent_directory, eu tenho subdiretórios rotulados como E-11_G e E-10_G. Dentro de cada um desses subdiretórios, eu tenho mais subdiretórios rotulados como E-2_U, E-1_U e E0_U. Em cada uma dessas pastas, estou executando comandos nesses arquivos: ander, ander.band, ander.data, ander.in e ander.log.

Aqui está uma foto melhor:

                               parent_directory
                                      ↓
                               E-11_G/ E-10_G/ 
                                  ↓
                          E-2_U/ E-1_U/ E0_U/ 
                            ↓
            ander  ander.band  ander.data  ander.in  ander.log

Eu quero escrever uma versão mais eficiente disso:

#!/bin/bash

cd parent_directory/E-11_G/E-2_U/; 
ls -l ander ander.band ander.data;
cat ander.in;
cat ander.log;
pwd;
cd ../E-1_U;
ls -l ander ander.band ander.data;
cat ander.in;
cat ander.log;
pwd;
cd ../E0_U;
ls -l ander ander.band ander.data;
cat ander.in;
cat ander.log;
pwd;
cd ../../E-10_G/E-2_U/;
ls -l ander ander.band ander.data;
cat ander.in;
cat ander.log;
pwd;
cd ../E-1_U;
ls -l ander ander.band ander.data;
cat ander.in;
cat ander.log;
pwd;
cd ../E0_U;
ls -l ander ander.band ander.data;
cat ander.in;
cat ander.log;
pwd;

Já consegui executar esse script com sucesso, mas preciso realmente de uma forma muito mais simples e eficiente de escrevê-lo, porque estou trabalhando com muito mais diretórios do que os que apresentei. Minha razão para fazer isso é porque eu preciso manter certos registros de cada um desses arquivos 'ander' para cada subdiretório. Estou basicamente planejando executar este script e exportar tudo o que aparece na janela do terminal em um arquivo de texto usando shell > exportar texto como. É por isso que eu quero os registros para cada diretório em ordem numérica.

Como posso tornar meu script mais eficiente? Esse é o tipo de coisa que estou querendo:

#!/bin/bash

cd parent_directory/;

do i= -11, -10 
   do j= -2, 0
      cd  E-i_G/E-j_U/;
      ls -l ander ander.band ander.data;
      cat ander.in;
      cat ander.log;
      pwd;
   end
end

Eu sei que isso é muito bem escrito em Fortran, mas há algo equivalente ou semelhante a isso no script do bash? Eu tenho tentado usar 'for loops', mas eu simplesmente não consigo escrevê-los de uma maneira que me desse os mesmos resultados que o meu primeiro script.

    
por SpaceKidd_N7 11.11.2014 / 05:12

2 respostas

4
cd parent_directory/

for i in {-11..-10}
do
   for j in -2 0
   do
      (
      cd  "E${i}_G/E${j}_U/"
      ls -l ander ander.band ander.data
      cat ander.in
      cat ander.log
      pwd
      )
   done
done

Notas:

  • Você pode percorrer um intervalo de números usando a notação de chaves:

    for i in {-11..-10}
    
  • Você também pode percorrer uma lista explícita de itens:

    for j in -2 0
    
  • Você pode alterar o diretório para um local que depende de variáveis:

    cd  "E${i}_G/E${j}_U/"
    
  • O argumento para o comando cd é um diretório especificado em relação ao diretório atual. Depois de termos feito o nosso trabalho nesse diretório, queremos voltar para o parent_directory. Há muitas maneiras de lidar com isso, mas uma maneira simples é fazer com que o comando cd e os comandos sejam executados nesse diretório em uma subshell, denotada por parens. Depois que saímos dos parênteses, o diretório é automaticamente restaurado para o que era antes.

por 11.11.2014 / 05:21
0

Como uma solução mais geral, você pode usar xargs . Desta forma, você pode dissociar a ação da lista de diretórios que deseja operar.

Primeiro, escreva um script que execute as ações de que você precisa:

perform_ander.sh

#!/bin/bash

# Exit immediately on error
set -e

if [[ $# -ne 1 ]] ; then
  echo "USAGE: $0 DIRECTORY" >&2
  exit 1
fi

cd "$1"

ls -l ander ander.band ander.data
cat ander.in
cat ander.log
pwd

Marque o script como executável:

chmod +x perform_ander.sh

Finalmente execute:

find -type d -name 'E*_U' | xargs -n1 ./perform_ander.sh

Explicação

encontrar

O comando find envia todos os arquivos correspondentes para stdout

-type d limita a pesquisa aos diretórios

-name 'E*_U' limita a pesquisa a diretórios que correspondem ao glob

xargs

O comando xargs usa sua entrada padrão como fonte de argumentos e chama os comandos fornecidos com esses argumentos.

-n1 especifica que não mais de 1 argumento é passado por vez.

    
por 12.11.2014 / 14:03