.flac
11のオーディオファイルを含むアルバムがあります。 (編集する:この問題が解決されたので、ファイルの正確な名前と内容が関連していないことが明らかになったので、名前を変更しました.)
> find . -name "*.flac"
./two.flac
./ten.flac
./nine.flac
./eight.flac
./seven.flac
./three.flac
./four.flac
./five.flac
./one.flac
./eleven.flac
./six.flac
.wav
特定のサンプルレートとビット深度を持つファイルに変換します。私はffmpeg
これにBashシェルを使います。次のコマンドを手動で呼び出すと、11個のファイルのそれぞれに対して完全に機能します。
ffmpeg -i "./six.flac" -sample_fmt s16 -ar 44100 "./six.wav"
while
ただし、各ファイルに対してこのコマンドを実行するためにループを作成するとき:
find . -name "*.flac" | sed "s/\.flac$//" | while read f; do ffmpeg -i "$f.flac" -sample_fmt s16 -ar 44100 "$f.wav"; done
これはうまくいきますが、8/11のファイルにのみ当てはまり、ffmpeg
3つの失敗に対して次のエラーメッセージが表示されます。
/ten.flac: No such file or directory
ree.flac: No such file or directory
ix.flac: No such file or directory
の場合、./ten.flac
相対ファイルパスの先頭部分は切り捨てられて.
絶対パスを形成しますが、他の2つ、および場合はベース名の先頭を含むより多くの文字が失われます。他の8つのファイルの一部が切り捨てられましたが、これにより正しい相対パスが生成されたため、この場合は続行できました。./three.flac
./six.flac
./
ffmpeg
同じループ構造を使用していますが、echo "$f"
callの代わりに使用するとffmpeg
出力に問題がないと思います。
> find . -name "*.flac" | sed "s/\.flac$//" | while read f; do echo "$f"; done
./two
./ten
./nine
./seven
./three
./four
./five
./one
./eleven
./six
"$f"
したがって、ループはよく構造化されており、各繰り返しで私が期待する方法で拡張されると確信しています。とにかく"$f.flac"
に渡されると、文字列の一部が切り捨てられますが、ffmpeg
特定のファイルにのみ適用されます。
最初の試みでこれらの動作が現れる理由を知りたいです。私はファイルを繰り返すか、変換するための代替案を探していません。 (他の種類のループを使用した2回目の試みはすべてのファイルに成功しました。)
編集する:私は問題を解決するようにyes |
見える配管を偶然見つけました。ffmpeg
既存のファイルを上書きするように求められないようにこれを追加しました.wav
。
編集する:説明してくれた@roaimaに感謝!ffmpeg
どちらread
も同じ標準入力ハンドルを継承するため、機会が発生する前に各行ffmpeg
の先頭にある文字を消費してread
一部のファイルパスが破損する可能性があります。これは標準入力に異なるハンドルをyes | ffmpeg ...
提供するため、これが機能する理由を説明します。ffmpeg
元のループはうまく機能しますffmpeg -nostdin ...
。http://mywiki.wooledge.org/BashFAQ/089。
答え1
ファイルのディレクトリツリー(例データセットに記載されていないが表示されない)がない場合は、単純なループを使用してファイルを処理できます。
for f in *.flac
do
w="${f%.flac}.wav"
ffmpeg -i "$f" -sample_fmt s16 -ar 44100 "$w"
done
ファイル階層がある場合は、それをfind
検索に統合できます。
find -type f -name '*.flac" -exec sh -c 'for f in "$@"; do w="${f%.flac}.wav"; ffmpeg -i "$f" -sample_fmt s16 -ar 44100 "$w"; done' _ {} +
flac
効率のために、すでに対応する割り当ての追加をスキップすることをお勧めしますwav
。実際にそれをしたくない場合は、コマンドをさらに最適化できます。w=
[ -s "$w" ] && continue
find -type f -name '*.flac" -exec sh -c 'ffmpeg -i "$1" -sample_fmt s16 -ar 44100 "${1%.flac}.wav";' _ {} \;
事前実行テストの場合は、プレフィックスを追加して実際の実行なしで実行される項目を確認してくださいffmpeg
。echo
(ただし、引用文は表示されませんのでご注意ください。)
ffmpeg
実際、問題は、処理する必要があるファイル名を噛むことに関連していることがわかりました。これはffmpeg
読み取りコマンドです標準入力、ファイルリストはループのパイプとしてレンダリングされましたwhile read …
(また、標準入力)。
解決策:ffmpeg -nostdin …
またはffmpeg … </dev/null
バラより