it-swarm-ja.com

期間ですべてのビデオファイルを検索

特定の期間のすべてのビデオファイルをあるディレクトリに移動したい。 この回答 ビデオファイルの長さを調べる方法を見つけました:

ffprobe -i some_video -show_entries format = duration -v quiet -of csv = "p = 0"

私はそれでこのようなことをしたかった:

find . -test <test for duration> -exec mv {} /path/to/target ';'

ただし、findはテスト用の任意のスクリプトをサポートしていないようです(-testスイッチはありません)。私は何か見落としてますか?これはfindでは単純に不可能ですか? pythonスクリプトを書くだけでいいですか?

2
user1785730

-exec-testとして使用できます。 1つのファイル名引数を取り、ファイルが条件を満たしている場合は0を終了し、それ以外の場合はゼロ以外を終了するスクリプトを記述します。システムにFFソフトウェア(例:ffprobe)ソフトウェアがないため、これを確認できませんが、次のようになります。

#!/bin/sh
if dur=$(ffprobe -i "$1" -show_entries format=duration -v quiet -of csv="p=0")
then
        [ "$dur" -ge 900 ]
        exit
else
        exit
fi

ffprobeが整数の秒数を出力すると仮定すると、15分以上の長さの動画をチェックします。 (mm:ssまたはss.dddが報告された場合、些細な変更はあなたに任せますが、インスピレーションについては以下の例を参照してください。)説明:ifが失敗すると、ffprobeは失敗します。その場合、下のexitに移動し、ffprobeからのエラーステータスで終了します。 ffprobeが成功した場合、その出力("$dur")をテストし、そのテストの結果で終了します。これも書くことができます

[ "$dur" -ge 900 ]  &&  exit 0  ||  exit 1

実際、全体スクリプトは実際には次のように減らすことができます。

dur=$(ffprobe -i "$1" -show_entries format=duration -v quiet -of csv="p=0")  \
                            &&  [ "$dur" -ge 900 ]

したがって、スクリプトをcheck_durのようなものと呼びます。その後、あなたはすることができます

find . -exec ./check_dur {} ';'-exec mv {} /path/to/target ';'

これが機能するのは、前述したように、-execがテストとして機能し、-execの後のものは、最初の-execが成功した(ステータス0で終了した)場合にのみ処理されるためです。

私が言ったように、私のシステムにはFFソフトウェア(例:ffprobe)ソフトウェアがないので、次のスクリプトでテストしました。

#!/bin/sh
if mod=$(stat -c%y "$1")
then
        mod=${mod#*-}
        mod=${mod%%-*}
        mod=${mod#0}
        [ $(( mod%2 )) = 0 ]
        exit
else
        exit
fi

これは、ファイルまたはディレクトリの変更日が偶数月であるかどうかをテストします。注:私の(en_US)システムでは、stat -c%y filenameは変更日をyyyy-mm-dd HH:MM:SS.ddddddddd -(TZ)の形式で出力します。したがって、上記のコード

  1. (左から)年を取り除いて、
  2. その月の後にすべてを取り除き、そして
  3. 先行する0がある場合は、それを取り除きます($((…))は先行ゼロを数値が8進数であることを示すものとして解釈するため、08および09のエラーを報告します)。

他のいくつかの注意事項:

  1. mvの場合、コマンドを次のように変更することで、コマンドを少し改善できます。

    find . -exec ./check_dur {} ';' -exec mv -t /path/to/target {} +
    

    これは、多くのファイルでmvを1回実行します。 -execはテストとして使用できないため、できません最初の-exec ... +でこれを実行します。

  2. 別のスクリプトを作成したくない場合は、sh -cを使用して、スクリプトをインライン化できます。例えば。、

    find . -exec sh -c 'dur=$(ffprobe -i "$1" -show_entries format=duration -v quiet -of csv="p=0") && [ "$dur" -ge 900 ]' sh {} ';'-exec mv -t /path/to/target {} +
    

    これにより、1行のミニスクリプト(sh -cの後の文字列)が作成され、ファイル名({})が引数として渡されます。 findの一部のバージョンでは、{}をミニスクリプトに組み込むことができますが、これは悪い考えです。

    • findのすべてのバージョンで機能するわけではなく、
    • それが機能する場合でも、一般に、一部のファイル名では失敗します(場合によっては壊滅的に失敗することさえあります)。
2
Scott