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
find
verwende , wo die Variable$file
zu deklarieren ist ? Und wo sollten Sie$target
deklarieren ? Sind allefind
nur 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