2017-02-25 4 views
3

私はFFmpegを使ってビデオをBashの画像に変換しようとしています。私はビデオのファイル名を使用して、対応する画像に名前を付けたい(整数に続けて)。他のファイルに名前を付けるためにファイル名を抽出するときのエラー

私は同じディレクトリ内のファイルのエクスポートされた場合、私はこれを行うことができた:私は、目的のディレクトリに画像をエクスポートした場合

for file in `find . -name "*.mp4"`; do ffmpeg -i $file -q 1 $file'_'%d.jpeg; done 

はしかし、私はエラーを得ました。 $ fileの値がファイル名だけでなくディレクトリであるように見えます。

私がしようとしていた:

for file in `find . -name "*.mp4"`; do ffmpeg -i $file -q 1 ~/testfolder/$file'_'%d.jpeg; done 

私の質問は:どのように私は正しくここに使用するファイル名だけを取り出すことができますか?

答えて

4

特殊な文字(まれに使用されているがファイル名で有効な改行を含む)で動作するため、このようにします。

destdir=~/testfolder/ 
while read -u 5 -r -d '' file 
do 
    name=$(basename "$file") 
    ffmpeg -i "$file" -q 1 "$destdir/${file}_%d.jpeg" </dev/null 
done 5< <(find . -name "*.mp4" -print0) 

basenameコマンドは外部プログラムです。シェル展開のみを使用して、次の行で同じ結果を得ることができます。

name=${file%/} 
name=${name##*/} 
+1

'/ dev/null'から' ffmpeg'の標準入力を 'find'コマンドの出力から読み込まないようにリダイレクトする必要があるかもしれないことに注意してください。 – chepner

+0

ループのファイル記述子を追加し、 '/ dev/null'から' ffmpeg'入力をリダイレクトしました。 'ffmpep'は実際に標準入力から読み込まれますか、それとももっと一般的な予防策ですか? – Fred

-1

bashコマンドbasenameをこれに使用できます。

この場合、以下のファイルのみをリストする必要があります

for file in $(find . -name "*.mp4"); do echo $(basename $file); done 

あなたはファイル名のみを得るためにあなたの元のコードで$(basename $file)を使用することができます。

+0

どうもありがとう、@Danny!できます!明確にするために、私は〜/ testfolder/$ファイル '_'%d.jpegを〜/ testfolder/$(basename $ file) '_'に置き換える必要がありました%d.jpeg – Shawn

+0

ああ、 。私はその答えを今修正しました。それがうまくいけば - あなたは受け入れられた答えとしてそれをマークできますか? –

+0

ちょうどいいよ!再度、感謝します! – Shawn

2

これにはベース名もループも必要ありません。 -type fを使用して、のディレクトリを報告し、結果を-execオプションと組み合わせてコマンドを直接実行することを避けることができます。

このような何かが、すべてのMP4ファイルのために働く必要があります:あなたは第二のファイルは、ファイル名にスペースを持っていますが、ある見ることができるように

$ find . -type f -name 'a*.txt' -exec bash -c 'echo ffmpeg -i $0 ' {} \; 
ffmpeg -i ./a.txt 
ffmpeg -i ./a spaced file.txt 
ffmpeg -i ./aa.txt 
ffmpeg -i ./cheatsheets/awk-cheat-sheet-gv.txt 

find . -type f -name '*.mp4' -exec bash -c 'ffmpeg -i $0 -q 1 $0'_'%d.jpeg' {} \; 

は小さなデモテストを参照してください。 findによって正しく処理されます。
そのような間隔のあるファイルは、for loopで壊れます。

このジョブをループで作成することを主張する場合は、これはFredからアドバイスされたwhileループでなければなりません。あなたはfind-printf機能を使用して、ベース名の使用を避けることができフレッド・ソリューションへの変形例として

find印刷物のmanページによると

while read -r -d '' file;do 
    ffmpeg -i "$file" -q 1 "${file}_%d.jpeg" 
done < <(find . -name "*.mp4" -printf %f\\0) 

-printf %fは、ファイル名が取り除かれ、\\0(ヌル文字を追加します)各ファ​​イル名の後に、名前にスペースやその他の特殊文字が含まれていても、正しいファイル名の扱いを保証します。

小テスト:

$ while read -r -d '' file;do echo "ffmpeg -i $file -q 1 ${file}_%d.jpeg";done < <(find . -name "a*.txt" -printf %f\\0) 
ffmpeg -i a.txt -q 1 a.txt_%d.jpeg 
ffmpeg -i a spaced file.txt -q 1 a spaced file.txt_%d.jpeg 
ffmpeg -i aa.txt -q 1 aa.txt_%d.jpeg 
ffmpeg -i awk-cheat-sheet-gv.txt -q 1 awk-cheat-sheet-gv.txt_%d.jpeg 
+0

ええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええ요私はそれが実際に質問に答えるとは思わない。 –

+0

私はそれが動作しないとは思わない。 findの-exec部分は私のものではなく、OP( 'ffmpeg -i $ 0 -q 1 $ 0 '_'%d.jpeg')によって構築されています。私はfindの中にそれを含めただけです。 –

関連する問題