Executar lote sobre os resultados do comando ls

1

Eu tenho uma pasta que tem várias pastas. Eu recebo a lista de todas as pastas usando o comando abaixo:

ls -1a -d */ 

Retorna algo como isto:

folder01/
folder02/
folder03/
...

Normalmente, guardo o resultado desse script em um arquivo de texto e, em seguida, crio um segundo arquivo de script de shell que processa as pastas retornadas pelo comando ls e o armazeno em um .sharquivo para executá-las como um lote. Portanto, o arquivo shell será algo como isto:

./process_folder.sh sample/folder01/
./process_folder.sh sample/folder02/    
./process_folder.sh sample/folder03/
./process_folder.sh sample/folder04/

Como você pode ver, eu corro ./process_folder.shsobre os resultados do comando ls e, infelizmente, há uma pequena alteração e eu adicionei sample/antes do nome de cada pasta.

Portanto, a questão é como posso fazer tudo isso usando um comando no meu shell? (Como eu me lembro, eu poderia usar |ou >mas não conseguia lembrar os detalhes).

VSB
fonte

Respostas:

3

Não analise programaticamente a saída de ls.

A saída de lsé projetada para consumo humano, não programático. Existem várias maneiras pelas quais a análise direta pode ser interrompida, mais ou menos sutilmente. Apenas como exemplo, se eu executar o comando que você deu, eu recebo uma saída diferente:

$ mkdir -p newdir/folder0{1,2,3}
$ cd newdir
$ ls -1ad */
folder01//
folder02//
folder03//
$

Vê aquelas barras duplas? Isso porque eu tenho um alias lspara ls --color=auto -F.

É melhor usar uma ferramenta projetada ou que possa pelo menos ser bem colocada em serviço para o trabalho. Sugiro recorrer a find.

$ mkdir -p newdir/folder0{1,2,3}
$ cd newdir
$ find . -mindepth 1 -maxdepth 1 -type d -printf './process_folder.sh sample/"%P"/\n'
./process_folder.sh sample/"folder03"/
./process_folder.sh sample/"folder01"/
./process_folder.sh sample/"folder02"/
$

-mindepth 1 -maxdepth 1limita a pesquisa apenas aos diretórios iniciais fornecidos (somente .neste caso) e exclui o próprio diretório inicial. -type dlimita as correspondências apenas aos diretórios. -printfé uma ação que a find pode executar, que imprime metadados sobre a entrada do diretório encontrada em um determinado formato; %Pno formato string é substituído pelo nome da entrada encontrada menos o diretório inicial. Veja man 1 findpara mais detalhes.

Se você deseja criar um script para execução posterior, redirecione a saída de findpara um arquivo:

$ find . -mindepth 1 -maxdepth 1 -type d -printf './process_folder.sh sample/"%P"/\n' > process_folders.sh

Se você deseja um único comando que executa os comandos imediatamente, canalize a saída findpara um shell:

$ find . -mindepth 1 -maxdepth 1 -type d -printf './process_folder.sh sample/"%P"/\n' | bash

É muito menos provável que isso ocorra e fornece o que você deseja, sem recorrer à reescrita sofisticada da saída de um comando. Como está, suspeito que a única coisa que pode resolver isso é se os nomes de diretório tiverem aspas duplas.

um CVn
fonte
Eu tenho três respostas certas, mas essa é a mais abrangente! De qualquer forma, eu deveria agradecer a Marius e Eugen
VSB
Além disso, -mindepth 1era um truque necessário.
VSB
@VSB Sim, sem -mindepth 1(ou com o padrão -mindepth 0especificado explicitamente), findtambém imprime o diretório inicial, o que obviamente não é o que você deseja.
um CVn
Ah, parece que este será executado, apenas imprimirá o resultado que pode ser usado como um script de shell dentro de um .sharquivo.
VSB
11
@VSB Claro, você poderia substituir -printf './process_folder.sh sample/"%P"/\n'por -printf 'printf "%%s\\n" "%P"; ./process_folder.sh sample/"%P"/\n'algo assim. Fazer isso imprimirá o nome de cada diretório à medida que é processado. (Sim, o dobro de% e \ são intencionais e necessários.)
um CVn
2

Você quer um loop:

for d in $(ls -1a -d */); do
  ./process_folder.sh "sample/$d"
done
Eugen Rieck
fonte
2

Você pode tentar o seguinte comando:

find . -type d -mindepth 1 -maxdepth 1 -exec bash -c ' /path/to/process_folder.sh "sample/${0##*/}" ' {} \;

Isso localiza os diretórios em perguntas e executa a pasta process_folder em cada um deles ao mesmo tempo: um único comando em vez de dois. Além disso, é imune a analisar problemas.

MariusMatutiae
fonte