gnu parallel: argumentos e espaços entre nomes de arquivos. Como resolver?

5

Isso está me deixando louco.

Eu tenho um monte de mp3 que eu quero transcodificar usando ffmpeg .

Estou tentando usar essa frase única (o script é maior, esta é a seção problemática):

find . -type f \( -iname \*.mp3 \) | parallel ffmpeg -i "{}" -acodec libmp3lame -ab 128k "$output_folder_with_spaces/{.}-128k.mp3" \;

(A seção iname está lá porque, no futuro, mais extensões poderão ser usadas)

Mas, mesmo usando as aspas em {} , sempre recebo No such file or directory , porque o mp3 tem o nome 01 - My song . E eu não sei se "$output_folder_with_spaces" vai funcionar também.

Eu pesquisei muito no Google, mas não consigo encontrar este exemplo: usar {} de find that {} tem espaços. Eu encontrei apenas quando usando uma variável ou caminhos codificados entre aspas.

Alguém sabe como posso resolver este problema de espaço, neste cenário?

    
por Somebody still uses you MS-DOS 15.05.2015 / 04:31

2 respostas

6

Você está usando a string de substituição errada com parallel ; você também precisará de -q para passar argumentos citados e não tenho certeza do que o \; à direita faz ...
Exemplo:

dirname_with_spaces="/home/don/my dir with spaces/"

(observe o% arrastado / no caminho atribuído a dirname_with_spaces ) e alguns mp3 nomes de arquivos com espaços em um diretório test , logo abaixo de cwd :

./test/Commercial DEMO - 09.mp3
./test/Commercial DEMO - 11.mp3
./test/Handel Royal Fireworks - 07.mp3
./test/Jazz Rag Ensemble - 10.mp3
./test/Mouret - Rondeau.mp3

usando

find . -type f -iname \*.mp3 | parallel -q ffmpeg -i {} -acodec \
libmp3lame -ab 128k "$dirname_with_spaces"{/.}-128k.mp3

produz os seguintes arquivos:

/home/don/my dir with spaces/Commercial DEMO - 11-128k.mp3
/home/don/my dir with spaces/Commercial DEMO - 09-128k.mp3
/home/don/my dir with spaces/Handel Royal Fireworks - 07-128k.mp3
/home/don/my dir with spaces/Jazz Rag Ensemble - 10-128k.mp3
/home/don/my dir with spaces/Mouret - Rondeau-128k.mp3

Observe a linha de comando q uoting ( parallel -q ) e o uso de:

{}
    Input line.

que significa o caminho de find output, e. ./test/Mouret - Rondeau.mp3
e

{/.}
    Basename of input line without extension. 

que se expande para Mouret - Rondeau e, em seguida, "$dirname_with_spaces"{/.} se expande para /home/don/my dir with spaces/Mouret - Rondeau

O último é bem diferente do {.} usado no seu comando

{.}
    Input line without extension.

que se expandiria para ./test/Mouret - Rondeau e, em seguida, "$dirname_with_spaces"{.} se expandiria para /home/don/my dir with spaces/./test/Mouret - Rondeau . Obviamente, isso causará um erro, pois não há /./test/ sob /home/don/my dir with spaces .

    
por 15.05.2015 / 15:11
2

Você entendeu mal a sintaxe de find . A sintaxe {} é usada em conjunto com -exec . Além disso, esses parênteses não são necessários; você só precisa deles se quiser substituir a ordem padrão de operações (por exemplo, não avaliar da esquerda para a direita). No geral, com exec, seria algo como isto (dividir para evitar rolagem horizontal):

find . -type f -iname \*.mp3 -exec \
    ffmpeg -i "{}" -acodec libmp3lame -ab 128k \
    "$output_folder_with_spaces/{}-128k.mp3" \;

Note que você terá arquivos com nomes como foo.mp3-128.mp3 ... Espero que seja o que você queria; Eu não tenho ideia do que {.} deveria significar - não é uma sintaxe válida, pelo menos com o GNU find.

Eu sugeriria usar lame diretamente, em vez de usar o FFmpeg (e se -ab usar o modo ABR em vez do modo VBR, eu sugeriria contra isso sem um bom motivo). Na verdade, eu sugiro contra a recodificação de MP3s em geral; melhor qualidade com a mesma taxa de bits seria obtida pela codificação de uma fonte sem perdas.

    
por 15.05.2015 / 05:34