Questão Aplique um comando a todos os arquivos em um diretório, um diretório por vez


Quero aplicar informações de repetição para todos os arquivos MP3 da minha coleção de músicas. Para fazer isso, estou usando uma ferramenta chamada mp3gain (no Linux).

Para aplicar o ganho do álbum corretamente, preciso executar o comando mp3gain por diretório. Em outras palavras, preciso encontrar um diretório, executar o mp3gain em todos os arquivos desse diretório e, em seguida, repetir para cada outro diretório. Até agora, eu inventei isso:

 find . -type d -exec mp3gain {}/*.mp3 \;

A saída é assim (mostrando apenas alguns dos muitos diretórios):

[...]
./dev2/Physicist/*.mp3
Can't open ./dev2/Physicist/*.mp3 for reading
./Real Things/*.mp3
Can't open ./Real Things/*.mp3 for reading

Parece-me que o '*'está sendo escapado, então ao invés de procurar por todos os arquivos terminados em' .mp3 ', ele está procurando por um arquivo chamado'*.mp3 '.

Qual comando devo usar?


2


origem


Tanto John T quanto michaelwells postaram soluções que funcionam bem, mas eu marquei a solução de John T como correta porque ele respondeu primeiro. Obrigado a todos. - NickG


Respostas:


Parece que não está circulando corretamente. Que tal algo como isso:

#!/bin/bash
OLDIFS=$IFS
IFS=$(echo -en "\n\b")
for dir in $(find . -type d)
do
        mp3gain $dir/*
done
IFS=$OLDIFS

como um único comando:

OLDIFS=$IFS;IFS=$(echo -en "\n\b");for dir in $(find . -type d);do mp3gain $dir/*;done;IFS=$OLDIFS

7



Será que isso vai lidar com nomes de espaços em dir corretamente? Eu nunca consegui obter o bash para loop para não dividir em espaços. - quack quixote
boa decisão. fixo! - John T
+1, boa solução. Eu acho que o 1-liner precisa export essas variáveis ​​(assumindo bash é o shell), mas caso contrário, parece certo. - quack quixote
Você deveria ser capaz de fazer IFS=$'\n\b' - Dennis Williamson
@ ~ quack: Não há necessidade de exportar essas variáveis. - Dennis Williamson


Pode não parecer legal, mas este comando irá encontrar todos os diretórios que contêm arquivos mp3 gravá-los em um arquivo temporário e, em seguida, passar por esse arquivo temp listando o conteúdo de cada diretório. Se você está feliz com a saída, você pode ir em frente e ligar o comando mp3gain no lugar do ls.

Definir a variável IFS como um caractere de nova linha é importante para que você possa trabalhar com arquivos e diretórios que contenham espaços.

A razão pela qual escolhi listar diretórios contendo mp3s primeiro é no caso de o mp3gain gerar um erro ao encontrar conjuntos vazios de arquivos. Desta forma, nunca encontra tal situação.

IFS=$'\n'; for i in `find -type f -iname *.mp3`; do dirname $i ; done | sort | uniq > ~/mp3directories.txt && for i in `cat ~/mp3directories.txt`; do ls -1 $i/*.mp3 ; echo ; done

1



O único problema com isso é que ele quer fazer um diretório de cada vez. Se os nomes dos arquivos forem classificados, eles serão capturados em todos os diretórios diferentes, em vez de processar cada arquivo em um diretório e, em seguida, passar para o próximo. - John T
Em primeiro lugar, agradeço a ambos pelo tempo necessário para responder. John T, o código do michaelwells mostra uma lista de diretórios, não nomes de arquivos. Eu testei e faz o que eu queria, embora apenas em diretórios contendo MP3s. - NickG


Você pode usar o Rebol funciona no Unix e no Windows

Como aplicar uma função a todos os arquivos em um diretório recursivamente

http://reboltutorial.com/blog/how-to-apply-a-function-to-all-files-in-a-directory-recursively/


-1