すべてのwavファイルとmp3ファイルをoggファイルに再帰的に変換するためにfindとFFmpegを使用しようとしています。これを行うには、次のbashスクリプトを作成しました。
#!/usr/bin/env bash
# Converts samples to ogg
find samples \( -iname '*.wav' -o -iname '*.mp3' \) -execdir ffmpeg -i "$(basename "{}")" -qscale:a 6 "${$(basename "{}")%.*}.ogg" \;
ただし、これを行うとエラーが発生します。
${$(basename "{}")%.*}.ogg: bad substitution
サフィックス付きのファイルのデフォルト名を返すように、最後の代替項目の形式をどのように指定する必要がありますか.ogg
?これがうまくいかないのはなぜですか?
答え1
--execdir
(Bash)シェルが呼び出され、次にffmpegが呼び出されると仮定しているようです。しかし、実際にはそうではありません。
-exec command ;
Execute command; true if 0 status is returned. All following
arguments to find are taken to be arguments to the command until
an argument consisting of `;' is encountered. The string `{}'
is replaced by the current file name being processed everywhere
it occurs in the arguments to the command, not just in arguments
where it is alone, as in some versions of find.
ffmpeg
呼び出され、find
it(ffmpeg
)は特別な構文で何をすべきかわかりません。
入力ファイル名のみに基づいて1つの変換を処理する小さなbashスクリプトを作成します-execdir
。
答え2
私私は最近例を書きました。シェルワンライナーをfind
コマンドに充填することも別のユースケースです。
変える:
find samples \( -iname '*.wav' -o -iname '*.mp3' \) -execdir ffmpeg -i "$(basename "{}")" -qscale:a 6 "${$(basename "{}")%.*}.ogg" \;
努力する:
find samples \( -iname '*.wav' -o -iname '*.mp3' \) -exec sh -c 'ffmpeg -i "$1" -qscale:a 6 "${1%.*}.ogg"' find-sh {} \;
これはfind-sh
任意のテキストです。シェルの$0
。find-sh
本当に良い名前だと思います。