
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, -exec
kann aber als Test beim find
Aufruf 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 ffprobe
alle 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 .jpg
einige 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 avconv
therein 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 avconv
ersetzen .Stream.*x720
was ist falsch an meiner kombinierten Befehlszeichenfolge?
find -exec
erfordert das Schließen mit\;
oder+
,es gibtnachdem Sie die Frage bearbeitet haben, gibt es$(
ohne)
""
verschachtelt (nicht verschachtelt) mit$()
,*720*
kann Shell-Globbing auslösen, sollte"*720*"
(ich spreche vonsh
, nicht von der äußeren Shell),- Die Ausgabe, die
avconv
Sie zu analysieren versuchen, geht anstderr
. 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.