Linux: Wie liste ich alle Videodateien mit einer Auflösung von genau 720p auf?

Linux: Wie liste ich alle Videodateien mit einer Auflösung von genau 720p auf?

Ich habe mehrere Videodateien mit unterschiedlichen Auflösungen. Jetzt möchte ich nur die Videodateinamen mit z. B. 720p-Auflösung auflisten. Ich bevorzuge Einzeiler in der Bash-Befehlszeile und kann hilfreiche Videoinformationen einschließlich der Auflösung erhalten, wenn ich Folgendes ausführe:

avconv -i video.mp4

aber diese Kombination:

find -exec sh -c 'if [[ "$(avconv -i {}") == *720* ]] ; then echo 720 found; fi;'

erzeugt den Fehler: exec - fehlendes Argument.

Ehrlich gesagt habe ich kaum Probleme mit Bash-Befehlsstrukturen, insbesondere kombinierten Befehlen. Was ist also falsch an meiner kombinierten Befehlszeichenfolge?

Danke schön.

Antwort1

Vielleicht führt dieser Befehl zu dem, was Sie suchen:

for i in *.mp4; do if [[ $(avconv -i $i) =~ .*720.* ]]; then echo $i; fi; done

Antwort2

Es mag überraschend sein, -execkann aber als Test beim findAufruf verwendet werden:

find -type f -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print

Der obige Befehl durchsucht Unterverzeichnisse. Um nur im aktuellen Verzeichnis zu suchen, verwenden Sie -maxdepth 1, z. B.:

find -maxdepth 1 -type f -exec …

Beachten Sie, dass ffprobealle Dateien getestet werden. Bei Nicht-Mediendateien schlägt der Test offensichtlich fehl, aber Sie erhalten möglicherweise Nicht-Video-Medien (wie ) in der endgültigen Ausgabe. Um dies zu vermeiden, sollten vor .jpgeinige zusätzliche Tests in verwendet werden , z. B.: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

Oder besser noch, Sie können den MIME-Typ mit folgendem testen 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

Lesen Sie weiter man find, um mehr zu erfahren.


BEARBEITEN:

Dieser Befehl (missbraucht) avconv, wie Sie es gewünscht haben:

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

Das Problem ist, dass jeder Aufruf von avconvtherein einen Fehler auslöst. Wir ignorieren ihn einfach und extrahieren die Informationen, die wir brauchen. Das ist eine ziemlich hässliche Lösung. Ich bin mir nicht ganz sicher, ob sich Ihr Code so verhält wie meiner, vielleicht müssen Sie ihn durch einen anderen regulären Ausdruck avconversetzen .Stream.*x720


was ist falsch an meiner kombinierten Befehlszeichenfolge?

  • find -execerfordert das Schließen mit \;oder +,
  • es gibt $(ohne) nachdem Sie die Frage bearbeitet haben, gibt es ""verschachtelt (nicht verschachtelt) mit $(),
  • *720*kann Shell-Globbing auslösen, sollte "*720*"(ich spreche von sh, nicht von der äußeren Shell),
  • Die Ausgabe, die avconvSie zu analysieren versuchen, geht an stderr. Ich denke, Sie müssen sie umleiten, bevor Sie sie analysieren können.
  • und vielleicht noch etwas anderes.

Antwort3

Ich kenne avconv nicht, ich verwende normalerweise ffmpeg. Wenn Sie es installieren, können Sie dieses Skript verwenden

#!/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

Antwort4

Ich habe vorerst eine brauchbare Lösung gefunden:

 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

Hier kann ich alle meine Videodateien in einer Schleife abspielen und deren Namen inklusive der Bedingung "720" ausgeben. Ohne den if-Teil könnte ich mir alle Videos und deren Auflösungen anzeigen lassen.

Ich habe dies mithilfe der anderen Antworten hier herausgefunden.

Wenn ich versuche, „find“ und „exec“ mit dem „do“-Teil der obigen Lösung zu kombinieren, erhalte ich als Ergebnis von Mediainfo für jedes Thema nur die Meldung „E: Dateilesefehler“:

 find -exec mediainfo "{}" \; -exec bash -c 'sm=$(mediainfo ${} | grep 720) : ; echo $sm' \;

Wie gesagt, die „if“-Konstruktion funktioniert (für das aktuelle Verzeichnis), aber ich werde versuchen, sie auch mit „find“ zum Laufen zu bringen.

verwandte Informationen