Passa uma lista de diretórios para um comando find

1

Como posso passar uma lista de diretórios para um comando find?

Imagine que você recebeu a lista como:

ls -d mydir*/

que produziria mydir1, mydir2 e assim por diante, mas exclui otherdirs1, otherdirs2.

Gostaria de executar o seguinte comando na lista:

find <put here the name of each dir>  -type f -name "*.mp3" -print0 | xargs -0 ...

Tentando executar este comando em cada diretório separadamente:

find -type f -name "*.mp3" -print0 |
xargs -0  mplayer -vo dummy -ao dummy -identify 2>/dev/null |
 perl -nle '/ID_LENGTH=([0-9\.]+)/ && ($t +=$1) && printf "%02d:%02d:%02d\n",$t/3600,$t/60%60,$t%60' |
 tail -n 1

Isso significa: encontrar os mp3s, executar o mplayer para obter meta-dados em cada arquivo, somar todos os ID_LENGTH de cada arquivo mp3, somar a soma de todos os mp3s no diretório.

    
por Quora Feans 06.09.2013 / 03:04

1 resposta

3

ls -d lista exatamente o que você passou (exceto os arquivos não existentes). Portanto, supondo que haja pelo menos um diretório cujo nome comece com mydir , é simplesmente

find mydir*/ -type f -name .mp3 -print0 | …

Observe que mydir*/ corresponde a links simbólicos para diretórios e find irá percorrer os diretórios vinculados.

Normalmente, xargs executa o comando o menor número de vezes possível, passando vários argumentos por vez. Se você precisar executar o comando para cada arquivo separadamente, diga-o:

find mydir*/ -type f -name .mp3 -print0 |
xargs -0 -n1 mplayer … |
perl …

Ou faça a coisa simples e use a opção -exec de find . Você perde a capacidade de filtrar os erros de find e mplayer separadamente.

find mydir*/ -type f -name .mp3 -exec mplayer -vo dummy -ao dummy -identify {} \; 2>/dev/null |
perl …

A propósito, por que imprimir todas as linhas se você só precisa da última?

… | perl -nle '/ID_LENGTH=([0-9\.]+)/ && ($t +=$1); END {printf "%02d:%02d:%02d\n",$t/3600,$t/60%60,$t%60}'

No bash depois de executar shopt -s globstar , em ksh após executar set -o globstar , ou em zsh fora da caixa, você também pode usar ** para corresponder arquivos em subdiretórios recursivamente.

mycommand mydir*/**/*.mp3
for f in mydir*/**/*.mp3; do …

Isso também corresponde a diretórios e links simbólicos cujo nome termina em .mp3 . O Bash atravessa links simbólicos para diretórios, enquanto o ksh e o zsh atravessam mydir* se eles são links simbólicos para diretórios, mas omitem links simbólicos quando recursing.

for f in mydir*/**/*.mp3; do
  mplayer -vo dummy -ao dummy -identify "$f" 2>/dev/null
done | perl …

ksh93 e zsh (mas não bash, dash ou pdksh) têm aritmética de ponto flutuante, então você nem precisa invocar outra ferramenta como Perl para fazer a soma.

typeset -F length=0
for f in mydir*/**/*.mp3; do
  length+=$(mplayer -vo dummy -ao dummy -identify "$f" 2>/dev/null |
            sed -n 's/^ID_LENGTH=//p')
done | perl …
printf "%02d:%02d:%02d\n" $((t/3600)) $((t/60%60)) $((t%60))
    
por 06.09.2013 / 03:10