AWKを使用してテキストファイルにコピーする結果/値を選択するスクリプト

AWKを使用してテキストファイルにコピーする結果/値を選択するスクリプト

bashスクリプトの最後のステップを助ける人がいますか?私がここまで来るのを手伝ってくれました。

#!/bin/bash

find . -type f \
       -name '*.mp4' -o -name '*.mkv' \
    -o -name '*.avi' -o -name '*.mov' |
while read -r file
do 
    size=$(stat -c %s "$file")
    duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file")
    codec=$(ffprobe -v error -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "$file")
    ratio=$(bc <<< "scale=2; $size / $duration")
    echo "$file: codec=$codec, size=$size, duration=$duration, ratio=$ratio" | tee -a /home/user/Downloads/logfile
    printf $ratio | awk '{print $1/1000}'| tee -a /home/user/Downloads/logfile
done

これで、すべての結果がテキストファイルに入ります。しかし、比率が次より大きいファイルのみを選択する方法はありますか?

@markp-fusoの要求に応じていくつかのことを明確にしました。

$ratioの例をいくつか使用して質問を更新してください。

$ratioの数字は、ビデオファイルのサイズ(バイト単位)をビデオファイルの持続時間(秒単位)で割ることによって生成されます。数字は約50kから1000kの間です。だから私はawk '{print $1/1000}'を使って50 - 1000の範囲にインポートしました。

そして、カットオフ/しきい値として何を使用しようとしますか? a) $ratio の値、b) awk で生成された値、または c) numfmt 呼び出しの結果に基づいてフィルタリングしますか?

良い点は、numfmt呼び出しを使用してバイトをメガバイトに増やしたいということです。ところで、それが切られました。したがって、削除できます。目的の結果が出るまで機能します。

./file1.mp4: codec=h264
aac, size=54886926, duration=94.900000, ratio=578365.92
578.366
./file2.mp4: codec=vp9
aac, size=15147100, duration=108.159000, ratio=140044.74
140.045
./file3.mp4: codec=vp9
aac, size=22306731, duration=109.947000, ratio=202886.21
202.886

長さが長いので、エンコード/縮小できるビデオ/オーディオファイルを見つけるためにこれを使用します。したがって、高い $ratio をエンコードできます。この値はスクリプトで簡単に調整できますが、約200〜400です。コーデックの効率によって異なります(使用されているコーデックを表示するために行を追加しました)。

だから、最終的に要件を満たすファイルだけを含むテキストファイルを持っていると思います。この場合、設定された比率よりも大きい。私は経験に基づいて決定を下します。

メモ:可能であれば、読み取れず(破損などのため)値のないファイルをテキストファイルに追加すると良いと思います。

比率を200に設定したと仮定すると、上記の3つの例に基づいて、txtファイルには次のものが含まれます。

./file1.mp4: codec=h264
aac, size=54886926, duration=94.900000, ratio=578365.92
578.366
./file3.mp4: codec=vp9
aac, size=22306731, duration=109.947000, ratio=202886.21
202.886

どんな助けでも大変感謝します。

乾杯

答え1

おそらく上部の近くでカットオフを宣言します。

# We only care about files with ratios GREATER than this:
cutoff=200000

その後、ループの下部付近で and コマンドをテストおよびステートメントにwhileラップします。echoprintfif

    ...
    ratio=$(bc <<< "scale=2; $size / $duration")
    rc=$(bc <<< "$ratio > $cutoff")
    if [[ "$rc" == "1" ]]
    then {
        echo "$file: codec=$codec, size=$size, duration=$duration, ratio=$ratio"
        awk '{print $1/1000}' <<< "$ratio"
    } | tee -a /home/user/Downloads/logfile
    fi
done

答え2

要求された問題を解決する前に、まずスクリプトのさまざまな問題を解決する必要があります。まず、findコマンドが間違っています。次に、改行文字を含むファイル名の場合、コマンドは失敗します。

お客様のfindエラーはオプションをグループ化していないためです。これは、あなたのコマンドが名前がegで終わるディレクトリも見つけることを意味します.mov。次のディレクトリを検討してください。

$ ls -lF
total 4
-rw-r--r-- 1 terdon terdon    0 Mar 18 18:37 'a bad'$'\n''file name.mp4'
drwxr-xr-x 2 terdon terdon 4096 Mar 18 18:38  foo.mov/

これには、ファイル(名前にスペースと改行文字が含まれています)とディレクトリが含まれていますfoo.mov。ファイルを処理したいだけですが、ディレクトリfindも返します。

$ find . -type f -name '*.mp4' -o -name '*.mkv' -o -name '*.avi' -o -name '*.mov' 
./foo.mov
./a bad?file name.mp4

すべての条件に適用するには、-type f次のようにグループ化する必要があります。回答前の質問に関して:

$ find . -type f \( -name '*.mp4' -o -name '*.mkv' -o -name '*.avi' -o -name '*.mov' \)
./a bad?file name.mp4

上記のように、括弧でグループ化すると(シェルで保護するにはエスケープするか引用符で囲む必要があります\()、コマンドは必要に応じてファイルのみを見つけることができます。'('次の問題は改行です。find印刷結果を\0改行文字の代わりにNULL()バイトで区切ることで、この問題を解決できます。 GNU find(Linuxシステムのデフォルト)を使用してこれを行うことができ、-print0他の検索実装にはを使用できます-printf

これらの名前を処理しないと、次のエラーが発生します。

$ find . -type f \( -name '*.mp4' -o -name '*.mkv' -o -name '*.avi' -o -name '*.mov' \) | while read -r file; do ls -l "$file"; done
ls: cannot access './a bad': No such file or directory
ls: cannot access 'file name.mp4': No such file or directory

正しい方法は次のとおりです。

$ find . -type f \( -name '*.mp4' -o -name '*.mkv' -o -name '*.avi' -o -name '*.mov' \) -print0 | while read -r -d '' file; do ls -l "$file"; done
-rw-r--r-- 1 terdon terdon 0 Mar 18 18:37 './a bad'$'\n''file name.mp4'

ここでは必須ではありませんが、お勧めしIFS=ます。バラよりこの回答たとえば、実際の操作は、入力区切り文字としてNULLを使用するようにオプションに指示することによって-d ''実行されます。readread

最後に、返される複数のコーデックを処理できる必要があります。これは、少なくとも私がテストしたファイルに対しては非常に一般的なものだからです。たとえば、

$ ffprobe -v error -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 foo.mkv 
hevc
ac3
ass

ffprobeしたがって、tr '\n' ','コマンドの出力などを介して改行を削除してください。

$ ffprobe -v error -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 foo.mkv | tr '\n' ','
hevc,ac3,ass,$

(最後は$私のプロンプトで、ここに末尾の改行文字がないことを示します。)

要約すると、すでに変数に比率があるので、必要なのは、ifその比率がしきい値を超えているかどうかを簡単に確認することです。なぜ2つの比率($ratiosum)があるのか​​わかりません$ratio / 1000。私が見るには、実際にテストした比率を使用する方が合理的に見えますが、それはあなたの決定です。ジョブスクリプトは次のとおりです。

#!/bin/bash

threshold=$1
if [ -z "$threshold" ]; then
  echo "No threshold given, using the default value of 200" >&2
  threshold=200
fi

logfile="/home/user/Downloads/logfile"

find . -type f \
  \( -name '*.mp4' -o -name '*.mkv' -o \
     -name '*.avi' -o -name '*.mov' \) -print0 | 
 while IFS= read -r -d '' file
 do 
    size=$(stat -c %s "$file")
    duration=$(ffprobe -v error -show_entries format=duration \
                       -of default=noprint_wrappers=1:nokey=1 "$file")
    codec=$(ffprobe -v error -show_entries stream=codec_name \
                    -of default=noprint_wrappers=1:nokey=1 "$file" |
              tr '\n' ',')
    ratio=$(bc <<< "scale=2; $size / $duration")

    # Check that a ratio was found, otherwise print an error
    if [[ -z "$ratio" ]]; then
      echo "No ratio found for '$file'" >&2
    else
      ## Not sure why you want two separate values for ratio but...
      ratio2=$(bc <<< "$ratio / 1000")

      if [[ $ratio2 -ge $threshold ]]; then
        printf '%s: codec=%s size=%s, duration=%s, ratio=%s\n' \
               "$file" "$codec" "$size" "$duration" "$ratio" | tee -a "$logfile"
        echo "$ratio2" | tee -a "$logfile"
      fi
    fi
done

これで、しきい値をパラメータとして(またはデフォルト値200なしで)実行できるようになりました。

script.sh 300

スクリプトに少しマイナーで、ほとんど外観的な変更を加え、いくつかの基本的なエラー処理を追加しましたが、まったく同じことを行う必要があります。出力は次のとおりです。

$ foo.sh 200
./file3.mkv: codec=h264,aac, size=764948534, duration=3488.131000, ratio=219300.40
219
./file7.mkv: codec=h264,aac, size=739550128, duration=3542.852000, ratio=208744.29
208
./file5.mkv: codec=h264,aac, size=688337512, duration=3439.637000, ratio=200119.23
200
./file1.mkv: codec=h264,aac, size=883534591, duration=3701.386000, ratio=238703.71
238
./file4.mkv: codec=h264,aac, size=828112726, duration=3769.898000, ratio=219664.49
219

関連情報