Executar lote sobre resultados do comando ls

1

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

ls -1a -d */ 

Ele retorna algo assim:

folder01/
folder02/
folder03/
...

Normalmente, armazeno o resultado desse script em um arquivo de texto e, em seguida, crio um segundo arquivo de script de shell que processa pastas retornadas pelo comando ls e as armazena no arquivo .sh para executá-las como um lote. Então, o arquivo shell será algo assim:

./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.sh sobre os resultados do comando ls e há uma pequena mudança e eu adicionei sample/ antes do nome de cada pasta.

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

    
por VSB 05.11.2016 / 14:41

3 respostas

4

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

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

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

Veja essas barras duplas? Isso é porque eu aliased ls to ls --color=auto -F .

É melhor usar uma ferramenta projetada para, ou pelo menos, ser bem informada em serviço para o trabalho. Sugiro mudar para 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 1 limita a pesquisa apenas aos diretórios iniciais fornecidos (somente . neste caso) e exclui o próprio diretório inicial. -type d limita as correspondências apenas para diretórios. -printf é uma ação que o find pode executar, que imprime metadados sobre a entrada de diretório encontrada em um determinado formato; %P na string de formato é substituído pelo nome da entrada encontrada menos o diretório inicial. Veja man 1 find para mais detalhes.

Se você quiser criar um script para ser executado posteriormente, redirecione a saída de find para um arquivo:

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

Se você quiser um único comando que execute os comandos imediatamente, canalize a saída de find em um shell:

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

É muito menos provável que isso quebre e forneça o que você deseja sem precisar reescrever a saída de um comando. Como é, suspeito que a única coisa que pode quebrar isso é se os nomes dos diretórios tiverem aspas duplas neles.

    
por 05.11.2016 / 14:54
2

Você quer um loop:

for d in $(ls -1a -d */); do
  ./process_folder.sh "sample/$d"
done
    
por 05.11.2016 / 14:50
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 encontra os diretórios em perguntas e executa process_folder em cada um deles ao mesmo tempo: um único comando em vez de dois. Além disso, é imune a problemas de análise.

    
por 05.11.2016 / 14:51