ファイルを再帰的に繰り返すときのスペースを含む名前の処理

ファイルを再帰的に繰り返すときのスペースを含む名前の処理

.mkvサブフォルダがあるフォルダ構造内のすべてのファイルを.mp4

現在のフォルダにのみ適用される標準行が表示されます。

for video in *.mkv; do ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mp4; rm "$video"; done

だから私は次のようなものを作ると思いました。

for video in $(find . -name *.mp4); do ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mkv; rm "$video"; done

しかし、空白を含むフォルダでは失敗するようです。誰でも私の間違いを指摘できますか?

ベストアンサー1

あなたの間違いは、findコマンド置換を使用することです。コマンド置換は常に単一の文字列を生成します。代替項目を引用符で囲まないと、文字列はスペース、タブ、および改行(デフォルト)に分割されます。分割された単語はファイル名のグロービングのために処理されます。結果の文字列はループが繰り返される文字列であり、これは目的の文字列ではありません。

現在のディレクトリで動作するループ(ダッシュで始まるファイル名の問題を解決するため):

for video in ./*.mkv; do
    ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mp4
    rm "$video"
done

globbingモードを有効にして再帰的に動作するように変更されました(一致がない場合にループが完全に実行されるのを防ぐために使用されます**)。nullglob

shopt -s globstar nullglob

for video in ./**/*.mkv; do
    ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mp4
    rm "$video"
done

上記の2つのループはファイルの種類を考慮しておらず、名前付きパターンとffmpeg一致する限り、シンボリックリンク、ディレクトリ、または他の非伝統的な種類のファイルを喜んで提供します。

または、パス名の再帰生成を次の宛先に委任しますfind(一般ファイルのみを選択)。

find . -name '*.mkv' -type f -exec sh -c '
    for video do
        ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mp4
        rm "$video"
    done' sh {} +

上記のコードはまた、パターンに一致する隠された名前を探します。これは、最初の2つのシェルループが実行しないことです(dotglobシェルオプションが有効になっていない場合)。

その他の関連質問:

おすすめ記事