ffmpegに渡されると、Bash変数は切り捨てられます。

ffmpegに渡されると、Bash変数は切り捨てられます。

.flac11のオーディオファイルを含むアルバムがあります。 (編集する:この問題が解決されたので、ファイルの正確な名前と内容が関連していないことが明らかになったので、名前を変更しました.)

> 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のファイルにのみ当てはまり、ffmpeg3つの失敗に対して次のエラーメッセージが表示されます。

/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";' _ {} \;

事前実行テストの場合は、プレフィックスを追加して実際の実行なしで実行される項目を確認してくださいffmpegecho(ただし、引用文は表示されませんのでご注意ください。)


ffmpeg実際、問題は、処理する必要があるファイル名を噛むことに関連していることがわかりました。これはffmpeg読み取りコマンドです標準入力、ファイルリストはループのパイプとしてレンダリングされましたwhile read …(また、標準入力)。

解決策:ffmpeg -nostdin …またはffmpeg … </dev/null

バラより

おすすめ記事