Como posso usar dois parâmetros de uma só vez com xargs?

15

Eu preciso converter vídeos, mas não sei onde eles estão, então eu preciso find deles. Como posso dar o resultado e um nome de arquivo de saída para FFmpeg com xargs ?

Eu já descobri que posso construir os dois parâmetros com este comando:

find . -iname "*.mov" -printf "%p %f\n"

Não consigo encontrar nada relacionado no manual xargs . Eu quero algo assim:

find . -iname "*.mov" -printf "%p %f\n" | xargs ffmpeg -i {param1} -f flv {param2}

Como posso fazer isso?

    
por kissgyorgy 07.01.2012 / 06:41

7 respostas

2

Algo parecido com isso fará o truque e preservará o caminho completo, gerenciará o espaço, renomeará folder/movie.mov para folder/movie.flv , etc.

find . -name "*.mov" | while read movie;do
  ffmpeg -i "$movie" -f flv "${movie%.mov}.flv"
done

E se eu entendi mal e você quer todos os filmes .flv no diretório atual, use este:

find . -name "*.mov" | while read movie;do
  ffmpeg -i "$movie" -f flv "$(basename "${movie%.mov}.flv")"
done
    
por 08.01.2012 / 03:57
9

A razão pela qual as pessoas usam xargs em combinação com o find é que vários nomes de arquivos serão passados para a mesma chamada de programa de qualquer programa xargs launch. Por exemplo, se find retornar os arquivos foo , bar e baz , o seguinte executará mv apenas uma vez:

find sourceDir [...] -print0 | xargs -0 mv -t destDir

Efetivamente, chama mv da seguinte forma:

mv -t destDir foo bar baz

Se você não precisa ou não quer este comportamento (como eu suponho que é o caso aqui), você pode simplesmente usar find ' -exec .

Nesse caso, uma solução fácil seria escrever um script de shell curto, como o seguinte:

#!/usr/bin/env bash
[[ -f "$1" ]] || { echo "$1 not found" ; exit 1 ; }
P="$1"
F="$( basename $P )"
ffmpeg -i "$P" -f flv "$F"

Salvar como myffmpeg.sh e executar chmod +x myffmpeg.sh . Em seguida, execute o seguinte:

find . -iname "*.mov" -exec /path/to/myffmpeg.sh {} \;

Isso invocará o script de shell uma vez para cada arquivo encontrado. O shell script, por sua vez, extrai o nome do arquivo do caminho completo e chama ffmpeg com os argumentos apropriados.

    
por 07.01.2012 / 07:52
3

Eu não obtive a solução esperada, então descobri a minha. @ Resposta do Daniel é bom, mas precisa de um script de shell. Um forro é mais rápido e eu gosto melhor :) solução mais simples do que escrever um script.

Eu poderia usar um argumento e processá-lo com basename e usando sh -c

find . -iname "*.mov" -print0 | xargs -0 -i sh -c 'ffmpeg -i {} -f flv 'basename {}''

O -i diz ao xargs para substituir {} pelo argumento atual.
Saída de comando dentro de '' impresso na saída padrão (recurso bash), então basename {} será avaliado como o nome do arquivo e impresso.
-0 para manipular nomes de arquivos especiais corretamente, mas você precisa passar parâmetros com a opção -print0 com find

    
por 07.01.2012 / 22:23
3

Você tem que fazer isso como todas as respostas, mas o uso EXATO dos xargs será algo assim:

echo argument1 argument2 argument3 | xargs -l bash -c 'echo this is first:$0 second:$1 third:$2' | xargs

Então, no seu caso, será:

find . -iname "*.mov" -printf "%p %f\n" | xargs -l bash -c 'echo ffmpeg -i $0 -f flv $1' | xargs

PS: Isso responde à pergunta sobre xargs para quem está procurando uma resposta exatamente para vários parâmetros xargs em um comando xargs .

    
por 02.09.2014 / 14:27
1

Por que não simplesmente mover as opções do ffmpeg para ajustar o formato dos resultados do comando find ?

find . -iname "*.mov" -printf "%p %f\n" | xargs -r -n2 ffmpeg -f flv -i

Observe a adição da opção -r ao xargs para evitar que ele execute ffmpeg se não houver .mov arquivos são encontrados.

Eu adicionei a opção -n2 para xargs para limitar o número de itens xargs para dois de cada vez. Nesse caso, os itens são o caminho do arquivo e o nome do arquivo. Se nenhuma opção -n estiver definida, xargs processará tantos itens de entrada quanto possível em uma única execução.

    
por 07.01.2012 / 10:11
1

Não tenho certeza se você pode ou como fazer isso com xargs.

Mas algo assim deve funcionar para você:

find . -iname "*.mov" -printf "%p %f\n" | while read -a HR ; do echo ffmpeg -i ${HR[0]} -f flv ${HR[1]} ;done
    
por 07.01.2012 / 07:21
0

Você pode executar o ffmpeg diretamente do comando find assim:

find . -iname "*.mov" -exec ffmpeg -i "%p" -f flv "%f" \;

Observe as aspas em torno dos parâmetros para o ffmpeg, caso haja espaços no nome do arquivo, e o ponto e vírgula escapado marque o final do comando executado.

    
por 07.01.2012 / 11:13