私は、bashスクリプトを実行していくつかの条件をチェックし、ffmpeg
を使用するという考えを持っています。 ディレクトリ内のすべてのビデオを任意の形式から.mkv
に変換します そしてそれはうまく機能しています!
問題は、for file in
を知らなかったということです ループは再帰的に機能しません(https://stackoverflow.com/questions/4638874/how-to-loop-through-a-directory-recursively)
しかし、私は「配管」をほとんど理解しておらず、例を見て、いくつかの不確実性を取り除くことを楽しみにしています。
私はこのシナリオを念頭に置いており、理解するのに大いに役立つと思います。
このbashスクリプトスニペットがあるとします:
for file in *.mkv *avi *mp4 *flv *ogg *mov; do
target="${file%.*}.mkv"
ffmpeg -i "$file" "$target" && rm -rf "$file"
done
現在のディレクトリで、*.mkv *avi *mp4 *flv *ogg *mov
を検索します。 次に、出力の拡張子が.mkv
になるように宣言します。 その後、元のファイルを削除し、出力を元のビデオとまったく同じフォルダに保存する必要があります。
-
これを再帰的に実行するように変換するにはどうすればよいですか?
find
を使用する場合 、変数$file
を宣言する場所 ?そして、どこで$target
を宣言する必要がありますか ?すべてfind
本当にワンライナー?私は本当にファイルを変数$file
に渡す必要があります 、条件チェックを実行する必要があるためです。 -
そして、(1)が成功したと仮定して、「出力を元のビデオとまったく同じフォルダに保存する必要がある」という要件が満たされていることを確認するにはどうすればよいですか?
承認された回答:
あなたはこのコードを持っています:
for file in *.mkv *avi *mp4 *flv *ogg *mov; do target="${file%.*}.mkv" ffmpeg -i "$file" "$target" && rm -rf "$file" done
これは現在のディレクトリで実行されます。それを再帰的なプロセスに変えるには、いくつかの選択肢があります。最も簡単な(IMO)は、find
を使用することです。 あなたが提案したように。 find
の構文 は非常に「UNIXライクではない」ですが、ここでの原則は、各引数をANDまたはOR条件で適用できるということです。ここでは、「this-filenameが一致するかthat-filenameがThenprint-itと一致する場合」と言います。 「。ファイル名のパターンは、シェルがそれらを取得できないように引用符で囲まれています(引用符で囲まれていないパターンがすべてある場合は、シェルが引用符で囲まれていないすべてのパターンを拡張する必要があることに注意してください。*.mp4
そしてあなたはjaneeyre.mp4
を持っていました 現在のディレクトリでは、シェルが*.mp4
に置き換わります。 一致すると、find
-name janeeyre.mp4
が表示されます 目的の-name *.mp4
の代わりに; *.mp4
の場合、さらに悪化します 複数の名前に一致します…)。角かっこには\
というプレフィックスが付いています また、シェルがサブシェルマーカーとしてそれらを実行しようとしないようにします(必要に応じて、代わりに角かっこを引用できます:'('
。
find . \( -name '*.mkv' -o -name '*avi' -o -name '*mp4' -o -name '*flv' -o -name '*ogg' -o -name '*mov' \) -print
この出力は、while
の入力に入力する必要があります 各ファイルを順番に処理するループ:
while IFS= read file ## IFS= prevents "read" stripping whitespace
do
target="${file%.*}.mkv"
ffmpeg -i "$file" "$target" && rm -rf "$file"
done
あとは、2つのパーツをパイプで結合するだけです|
find
の出力が while
の入力になります ループ。
このコードをテストしている間、両方のffmpeg
のプレフィックスを付けることをお勧めします およびrm
echo
を使用 だからあなたは何をするかを見ることができます 実行される–そしてどのパスで実行されるか。
echo
を含む最終結果は次のとおりです。 テストに推奨するステートメント:
find . \( -name '*.mkv' -o -name '*avi' -o -name '*mp4' -o -name '*flv' -o -name '*ogg' -o -name '*mov' \) -print |
while IFS= read file ## IFS= prevents "read" stripping whitespace
do
target="${file%.*}.mkv"
echo ffmpeg -i "$file" "$target" && echo rm -rf "$file"
done