
解像度の異なるビデオ ファイルがいくつかあります。ここでは、たとえば 720p 解像度のビデオ ファイル名のみを一覧表示したいと思います。私は bash コマンド ラインでワンライナーを好み、次のコマンドを実行すると解像度を含む役立つビデオ情報を取得できます。
avconv -i video.mp4
しかし、この組み合わせ:
find -exec sh -c 'if [[ "$(avconv -i {}") == *720* ]] ; then echo 720 found; fi;'
エラーが発生します: exec - 引数がありません。
正直に言うと、私は bash コマンド構造、特に複合コマンドにはほとんど苦労したことがありません。では、複合コマンド文字列の何が間違っているのでしょうか?
ありがとう。
答え1
おそらく、このコマンドで目的を達成できるでしょう:
for i in *.mp4; do if [[ $(avconv -i $i) =~ .*720.* ]]; then echo $i; fi; done
答え2
驚くかもしれませんが、呼び出し-exec
時のテストとして使用できますfind
。
find -type f -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print
上記のコマンドはサブディレクトリまで降りていきます。現在のディレクトリ内を検索するには-maxdepth 1
、 のみを使用します。例:
find -maxdepth 1 -type f -exec …
はすべてのファイルをテストすることに注意してくださいffprobe
。メディア以外のファイルでは明らかに失敗しますが、.jpg
最終出力にビデオ以外のメディア ( など) が含まれる可能性があります。これを回避するには、find
の前に でいくつかの追加テストを使用する必要があります-exec
。例:
find -maxdepth 1 -type f \( -iname "*.avi" -o -iname "*.mp4" -o -iname "*.mkv" \) -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print
または、次のようにして MIME タイプをテストすることもできますfile
。
find -maxdepth 1 -exec sh -c 'file --mime-type "$1" | grep -q "video/"' sh {} \; -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print
man find
詳細については、こちらをお読みください。
編集:
このコマンドはavconv
、要求どおりに を(誤って)使用します:
find -exec sh -c 'file --mime-type "$1" | grep -q "video/"' sh {} \; -exec sh -c 'avconv 2>&1 -i "$1" | grep -q "Stream.*x720"' sh {} \; -print
問題は、avconv
therein の呼び出しごとにエラーが発生することです。これを無視して、必要な情報を抽出します。これは少々見苦しい解決策です。あなたの方法が私の方法と同じかどうかはよくわかりません。他の正規表現にavconv
置き換える必要があるかもしれません。Stream.*x720
結合されたコマンド文字列の何が間違っているのでしょうか?
find -exec
\;
またはで閉じる必要があります+
。質問を編集した後、$(
)
""
インターリーブ(ネストされていない)が存在します$()
。*720*
シェルグロビングを引き起こす可能性があります。 (外側のシェルではなく、"*720*"
について話しています)sh
avconv
解析しようとするの出力は になりますstderr
。解析する前にリダイレクトする必要があると思います。- そしておそらく他の何か。
答え3
avconvは知りません。普段はffmpegを使っています。インストールすればこのスクリプトが使えます。
#!/bin/bash
OIFS="$IFS"
IFS=$'\n'
files=$(find ./ -type f -exec ls {} + | grep ".*\.mpg$\|.*\.avi$\|.*\.mkv$\|.*\.mp4$"| cut -c3-)
for f in ${files}
do
resolution=$(ffprobe -v error -select_streams v:0 -show_entries
stream=height -of csv=s=x:p=0 ${f})
printf "%-100s %-10s\n" $f $resolution
done
答え4
現時点では、使用可能な解決策を見つけました:
for i in ls *.m??; do sm=$(mediainfo $i | grep Height | sed 's/ //g');if [[ "$sm" == *720* ]]; then printf "Video: %-s $i %-s $sm \n"; fi; done
ここで、すべての m?? ビデオ ファイルをループし、その名前を「720」条件を含めて出力できます。if 部分を省略すると、すべてのビデオとその解像度を表示できます。
私はここにある他の回答の助けを借りてこれを解決しました。
find と exec と上記のソリューションの do 部分を組み合わせようとすると、各件名について mediainfo からの結果として「E: ファイル読み取りエラー」というメッセージのみが表示されます。
find -exec mediainfo "{}" \; -exec bash -c 'sm=$(mediainfo ${} | grep 720) : ; echo $sm' \;
前述したように、「if」構文は機能します (実際のディレクトリに対して) が、find でも実行できるようにしてみます。