この行がファイルを破損するのはなぜですか?

この行がファイルを破損するのはなぜですか?

いくつかのビデオを一括エンコードするのに役立つように、

find -name '*.mkv' -exec HandBrakeCLI -Z "Android Tablet" \
  -c "1-3" -m -O --x264-tune film -E copy --decomb -s 1 -i {} \
  -o `echo {} | tr mkv m4v` \;

しかし、これは致命的に失敗します。すべての700-900MBファイルを36KBファイルに置き換えます。

HandBrakeは、エンコードが進行したときにのみビデオファイルのプロパティを読み取って印刷できることに注目する価値があります。ファイルが無効なためです。だから到着すると上書きが起こると思います...

-o `echo {} | tr mkv m4v`

...しかし、なぜこれが起こるのかわかりません。出力ファイル名をeverything.mkvからeverything.m4vに変更したいと思います。

ファイル名にスペースがありません。12-the-revenge.mkvたとえば、次の形式です。

答え1

逆引用符表現:(echo {} | tr mkv m4vつまり、いいえさまざまな理由で、以下を参照してください)がfindコマンドを解析するときに一度拡張されます。を使用すると、bash通常は次のように拡張されます{}

$ echo {} | tr mkv m4v
{}

実際、これは空の行を出力する魚を除いて、私のコンピュータにインストールされているすべてのシェルで発生します。 1つを使用しないと仮定すると、fish実際に表示されるパラメータfindは次のとおりです。

find -name '*.mkv' -exec HandBrakeCLI -Z "Android Tablet" \
-c "1-3" -m -O --x264-tune film -E copy --decomb -s 1 -i {} \
-o {} \;

簡単に言えば、HandBrakeCLI入力と出力の両方が同じファイルを提供し、症状の説明が正確ではありませんが、これがあなたが見ているものだと思います。

残念ながら、findにタスクで実行したい拡張置換を実行する簡単な方法はありません-exec。にコマンドを渡すことでこれを行うことができますが、bash -cこの場合はコマンドラインに追加の引用が含まれて混乱します。よりクリーンで読みやすい解決策は、その引数を繰り返すシェルスクリプトファイルを作成することです。

ファイル:(mkvtom4v.sh必ず確認してくださいchmod a+x mkvtom4v.sh

#!/bin/bash
for file in "$@"; do
  HandBrakeCLI -Z "Android Tablet" -c "1-3" -m -O \
               --x264-tune film -E copy --decomb -s 1 \
               -i "$file" -o "${file/%.mkv/.m4v}"
done

その後、findで呼び出します。

find /path/to/directory -name '*.mkv' -exec /path/to/mkvtom4v.sh {} +

いくつかの注意:

  1. バックティック()を使用しないでくださいsome command。長年の間、もはや使用されていません。を使用すると、$(some command)読みやすく、ネストできます。

  2. tr確かにあなたが望むものではありません。文字ごとに翻訳します。たとえば、これを行うと、tr aeiou AEIOUすべてのコレクションがUppErcAsEになります。すべてtr mkv m4vに変更されます。詳細については(または)を参照してください。k4man trinfo tr

  3. "${file/%.mkv/.m4v}"bashの特殊検索と代替構文です。この場合、これは次のことを意味します。 「値を取得して(このコンテキストでは「次に終了」を意味します)、終了する$file場合」に置き換えます。変数の値を編集する方法はいくつかあります。 「パラメータ拡張」を検索してみてください。.mkv%.m4vman bash

  4. GNU findを使用すると、コマンドの最後に(代わりに)を{} +使用できます。できるだけ多くの検索されたファイル名に置き換えられます。詳細は参照してください。-exec\;info find

関連情報