web-dev-qa-db-ja.com

xargsで2つのパラメーターを同時に使用するにはどうすればよいですか?

動画を変換する必要がありますが、どこにあるかわからないので、findする必要があります。 xargsFFmpeg に結果と出力ファイル名を与えるにはどうすればよいですか?

このコマンドで2つのパラメーターを作成できることはすでにわかりました。

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

xargsマニュアルに関連するものは見つかりません。私はこのようなものが欲しい:

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

これどうやってするの?

18
kissgyorgy

このようなものはトリックを行い、フルパスを保持し、スペースを処理し、名前を変更しますfolder/movie.movからfolder/movie.flvなど.

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

そして、私があなたを誤解していて、現在のディレクトリにあるすべての.flvムービーが必要な場合は、代わりにこれを使用してください。

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

xargsをfindと組み合わせて使用​​する理由は、xargsが起動するすべてのプログラムの同じプログラム呼び出しに複数のファイル名が渡されるためです。たとえば、findがファイルfoobar、およびbazを返す場合、以下はmvを1回だけ実行します。

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

効果的には、次のようにmvを呼び出します。

mv -t destDir foo bar baz

この動作が必要ない、または必要ない場合は(ここではそうだと思います)、find-execを使用できます。


この場合、簡単な解決策は、次のような短いシェルスクリプトを記述することです。

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

myffmpeg.shとして保存し、chmod +x myffmpeg.shを実行します。次に、以下を実行します。

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

これにより、ファイルが見つかるたびにシェルスクリプトが呼び出されます。次に、シェルスクリプトはフルパスからファイル名を抽出し、適切な引数を指定してffmpegを呼び出します。

9
Daniel Beck

期待した解決策が得られなかったので、自分の解決策を見つけました。 @Danielの答えは良いですが、シェルスクリプトが必要です。ワンライナーは速く、私はそれが好きです:)また、スクリプトを書くよりもシンプルなソリューションです。

1つの引数を使用して、basenameで処理し、sh -cを使用することができます

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

-iは、xargsに{}を現在の引数で置き換えるように指示します。
内のコマンド出力は、標準出力(bash機能)に出力されるため、basename {}は、ベアファイル名として評価され、出力されます。
-0は、特殊ファイル名を適切に処理するためのものですが、-print0オプションを使用してパラメーターを渡す必要があります。

4
kissgyorgy

これまでのすべての回答と同じように行う必要がありますが、xargsの正確な使用法は次のようになります。

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

したがって、あなたの場合は次のようになります:

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

PS:これは、1つのxargsコマンドで複数のxargsパラメーターに対する回答を正確に探している人のためのxargsに関する質問に答えます。

3
sauliux zyziux

名前バインディングを使用して(およびファイル名にスペースが含まれる問題を回避するために別のセパレーターを使用して)Zoredacheの回答の代替案:

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

もちろん、他の回答が使用したfind -a array引数でセパレータを使用することもできますが、名前付き引数の方がわかりやすい場合があります。

1
wolf1oo

Xargsを使用してできるかどうか、またその方法はわかりません。

しかし、このようなものがあなたのために働くはずです:

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

ffmpegのオプションを単純に移動して、findコマンドからの結果のフォーマットに合わせてみませんか?

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

-rオプションがxargsに追加され、実行されないようにするffmpeg。movファイルがない場合見つかりました。

-n2オプションをxargsに追加して、アイテムの数を制限しましたxargs 一度に2つまで処理します。この場合の項目は、ファイルパスとファイル名です。 -nオプションが設定されていない場合、xargsは1回の実行でできるだけ多くの入力項目を処理します。

1
ZaSter

次のように、findコマンドから直接ffmpegを実行できます。

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

ファイル名にスペースがあり、エスケープされたセミコロンが実行されたコマンドの終わりを示している場合は、ffmpegのパラメーターを囲む引用符に注意してください。

0
Randy Orrison