Ich habe diese Idee, ein Bash-Skript auszuführen, um einige Bedingungen zu überprüfen und ffmpeg zu verwenden um alle Videos in meinem Verzeichnis von jedem Format in .mkv zu konvertieren und es funktioniert großartig!
Die Sache ist, ich wusste nicht, dass ein for file in Schleife funktioniert nicht rekursiv (https://stackoverflow.com/questions/4638874/how-to-loop-through-a-directory-recursively)
Aber ich verstehe „Piping“ kaum und freue mich darauf, ein Beispiel zu sehen und einige Unklarheiten auszuräumen.
Ich habe dieses Szenario im Sinn, von dem ich denke, dass es mir sehr helfen würde, es zu verstehen.
Angenommen, ich habe dieses Bash-Skript-Snippet:
for file in *.mkv *avi *mp4 *flv *ogg *mov; do
target="${file%.*}.mkv"
ffmpeg -i "$file" "$target" && rm -rf "$file"
done
Was es tut, ist, für das aktuelle Verzeichnis nach *.mkv *avi *mp4 *flv *ogg *mov zu suchen deklarieren Sie dann die Ausgabe mit der Erweiterung .mkv Löschen Sie anschließend die Originaldatei, dann sollte die Ausgabe in demselben Ordner gespeichert werden, in dem sich das Originalvideo befindet.
-
Wie kann ich dies konvertieren, um rekursiv zu laufen? wenn ich
findverwende , wo die Variable$filezu deklarieren ist ? Und wo sollten Sie$targetdeklarieren ? Sind allefindnur wirklich Einzeiler? Ich muss die Datei wirklich an eine Variable$fileübergeben , da ich die Bedingungsprüfung noch ausführen muss. -
Und unter der Annahme, dass (1) erfolgreich ist, wie kann sichergestellt werden, dass die Anforderung „dann sollte die Ausgabe in demselben Ordner gespeichert werden, in dem sich das Originalvideo befindet“ erfüllt ist?
Akzeptierte Antwort:
Sie haben diesen Code:
for file in *.mkv *avi *mp4 *flv *ogg *mov; do target="${file%.*}.mkv" ffmpeg -i "$file" "$target" && rm -rf "$file" done
die im aktuellen Verzeichnis läuft. Um es in einen rekursiven Prozess umzuwandeln, haben Sie ein paar Möglichkeiten. Am einfachsten (IMO) ist die Verwendung von find wie du vorgeschlagen hast. Die Syntax für find ist sehr „UNIX-unähnlich“, aber das Prinzip hier ist, dass jedes Argument mit UND- oder ODER-Bedingungen angewendet werden kann. Hier sagen wir „Wenn dieser Dateiname übereinstimmt ODER dieser Dateiname übereinstimmt, dann drucken Sie es aus.“ “. Die Dateinamenmuster werden in Anführungszeichen gesetzt, damit die Shell sie nicht finden kann (denken Sie daran, dass die Shell für das Erweitern aller Muster ohne Anführungszeichen verantwortlich ist, wenn Sie also ein Muster ohne Anführungszeichen von *.mp4 hätten und Sie hatten janeeyre.mp4 in Ihrem aktuellen Verzeichnis würde die Shell *.mp4 ersetzen mit der Übereinstimmung und find würde -name janeeyre.mp4 sehen anstelle Ihres gewünschten -name *.mp4; schlimmer wird es, wenn *.mp4 stimmt mit mehreren Namen überein…). Den Klammern wird \ vorangestellt auch um zu verhindern, dass die Shell versucht, sie als Subshell-Marker zu verwenden (wir könnten stattdessen die Klammern zitieren, wenn dies bevorzugt wird:'(' ).
find . \( -name '*.mkv' -o -name '*avi' -o -name '*mp4' -o -name '*flv' -o -name '*ogg' -o -name '*mov' \) -print
Die Ausgabe davon muss in die Eingabe von while eingespeist werden Schleife, die jede Datei der Reihe nach verarbeitet:
while IFS= read file ## IFS= prevents "read" stripping whitespace
do
target="${file%.*}.mkv"
ffmpeg -i "$file" "$target" && rm -rf "$file"
done
Jetzt müssen die beiden Teile nur noch mit einer Pipe | verbunden werden damit die Ausgabe von find wird zur Eingabe von while Schleife.
Während Sie diesen Code testen, empfehle ich Ihnen, beiden ffmpeg voranzustellen und rm mit echo damit Sie sehen können, was würde ausgeführt werden – und mit welchen Pfaden.
Hier ist das Endergebnis, einschließlich des echo Anweisungen, die ich zum Testen empfehle:
find . \( -name '*.mkv' -o -name '*avi' -o -name '*mp4' -o -name '*flv' -o -name '*ogg' -o -name '*mov' \) -print |
while IFS= read file ## IFS= prevents "read" stripping whitespace
do
target="${file%.*}.mkv"
echo ffmpeg -i "$file" "$target" && echo rm -rf "$file"
done