Come posso usare due parametri contemporaneamente con xargs?


18

Devo convertire i video, ma non so dove siano, quindi ho bisogno di findloro. Come posso assegnare il risultato e il nome di un file di output a FFmpeg con xargs?

Ho già scoperto che posso costruire i due parametri con questo comando:

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

Non riesco a trovare nulla di correlato nel xargsmanuale. Voglio qualcosa del genere:

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

Come posso fare questo?


Quelli di voi che si imbattono in questa domanda perché state cercando una risposta su più argomenti con xargs in generale potrebbero voler controllare stackoverflow.com/questions/3770432/… .
— Chris Oldwood,

Risposte:


4

Qualcosa del genere farà il trucco e manterrà il percorso completo, gestirà lo spazio, rinominerà folder/movie.movin folder/movie.flv, ecc.

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

E se ti ho frainteso e vuoi tutti i film .flv nella directory corrente, usa invece questo:

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

3
Se lo vuoi come oneliner, basta mettere tutto su una linea. ;)
— Mattias Ahnberg

9

Il motivo per cui le persone usano xargsin combinazione con find è che più nomi di file verranno passati allo stesso richiamo del programma di qualunque programma venga xargsavviato. Ad esempio, se findrestituisce i file foo , bar e baz , quanto segue verrà eseguito mvuna sola volta:

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

In effetti, chiama mvcome il seguente:

mv -t destDir foo bar baz

Se non avete bisogno o volete questo comportamento (come presumo sia il caso qui), si può semplicemente utilizzare finds' -exec.


In questo caso, una soluzione semplice sarebbe quella di scrivere uno script di shell corta, come il seguente:

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

Salva come myffmpeg.shed esegui chmod +x myffmpeg.sh. Quindi, esegui quanto segue:

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

Questo invocherà lo script della shell una volta per ogni file trovato. Lo script shell a sua volta estrae il nome del file dal percorso completo e chiama ffmpegcon gli argomenti appropriati.


4

Non ho ottenuto la soluzione che mi aspettavo, quindi ho scoperto la mia. @La risposta di Daniel è buona, ma ha bisogno di uno script di shell. Una riga è più veloce e mi piace di più :) soluzione anche più semplice rispetto alla scrittura di una sceneggiatura.

Potrei usare un argomento ed elaborarlo con basenamee usandosh -c

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

-I dice a xargs di sostituire {}con l'argomento corrente.
L'output del comando all'interno di `` stampato sull'output standard (funzione bash) basename {}verrà quindi valutato come il nome del file nudo e stampato.
-0 per gestire correttamente nomi di file speciali, ma è necessario passare i parametri con l'opzione -print0 con find


3

Devi farlo come tutte le risposte lassù, ma l'uso ESATTO di xargs sarà qualcosa del genere:

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

Quindi nel tuo caso sarà:

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

PS: Questo risponde alla domanda su xargs per coloro che cercano una risposta esattamente per più xargsparametri in un solo xargscomando.


1

Perché non spostare semplicemente le opzioni di ffmpeg per adattarle al formato dei risultati dal comando find ?

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

Notare l'aggiunta dell'opzione -r a xargs per impedire l'esecuzione di ffmpeg se non viene trovato alcun file .mov .

Ho aggiunto l' opzione -n2 a xargs per limitare il numero di elementi processi xargs alla volta. In questo caso, gli elementi sono il percorso del file e il nome del file. Se non è impostata alcuna opzione -n , xargs elaborerà il maggior numero possibile di elementi di input in un'unica esecuzione.


Questo non funzionerà una volta trovato più di un file AFAICT.
— Daniel Beck

Questo funziona solo una volta anche per me, ma non capisco perché si interrompa dopo il primo. Qualche idea ?
— kissgyorgy,

in realtà non funziona
— kissgyorgy

Daniel-Beck e @Walkman avevano ragione sulla singola esecuzione. Per risolvere questo problema, ho modificato questa risposta per limitare il numero di elementi che xargs elabora alla volta tramite l' opzione -n2 . Senza -n2 , xargs viene eseguito una sola volta se è in grado di gestire il numero di elementi di input che riceve attraverso la pipe. Va inoltre sottolineato che questa soluzione funziona solo quando i nomi dei file e i percorsi dei file non includono spazi bianchi.
— ZaSter

1

Non sono sicuro se puoi o come farlo con xargs.

Ma qualcosa del genere dovrebbe funzionare per te:

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

1
Questo non gestisce correttamente gli spazi nei nomi / percorsi dei file, vero?
— Daniel Beck

1

Un'alternativa alla risposta di Zoredache usando l'associazione dei nomi (e usando diversi separatori per evitare il problema degli spazi nei nomi dei file):

IFS="\t" find -iname "*.mov" -printf "%p\t%f\n" | while read path file; do
    ffmpeg -i $path -f flv $file
done

Ovviamente puoi anche usare i separatori con l' find -a arrayargomento usato dall'altra risposta, ma a volte argomenti più chiari sono più comprensibili.


0

Puoi eseguire ffmpeg direttamente dal comando find in questo modo:

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

Nota le virgolette attorno ai parametri su ffmpeg, nel caso in cui vi siano spazi nel nome del file e il punto e virgola sfuggito segna la fine del comando eseguito.


Hai documentazione per il comportamento di -exec che interpreta anche i segnaposto di formattazione di printf?
— Daniel Beck

No. Brain scoreggia: stavo pensando che% p e% f fossero cose da trovare, non cose da stampare. Ho votato per la tua risposta.
— Randy Orrison,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.