[Ubuntu] Mehrere Befehle nacheinander ausführen lassen

Crys

Lt. Commander
Registriert
Apr. 2009
Beiträge
1.634
Zur Zeit muss ich recht viele Dateien konvertieren, komprimieren und mir per ftp schicken lassen. Dazu verwende ich immer die selben Befehle, nur mit anderer Datei. Das möchte ich aber gerne vereinfachen lassen, sodass ich nur einen einzelnen Befehl eingeben muss und der alles abarbeitet oder ich die Befehle verkettet ausführe. Wie geht das?

Typische Schritte sind:
1.) screen -S Umwandlung_DATEI (neuen Screen öffnen, damit man parallel arbeiten kann)
2.) HandBrakeCLI optionen PFAD/DATEI zielpfad1/DATEI
3.) 7z optionen zielpfad1/DATEI zielpfad2/DATEI
4.) wput zielpfad2/DATEI.* optionen
5.) screen -d Umwandlung_DATEI (nach erfolgreichen durchlaufen Screen schließen, ist aber nicht wichtig)
Es ist immer das selbe, nur PFAD und DATEI ist jedes mal anders.

Ich habe schon mit Verkettungen && und Variablen $ probiert, aber ohne Erfolg. Muss man dafür ein Script schreiben? Das hat aber mit den screen Befehlen nicht geklappt.

Danke schon mal :)
 
moin
schätze, das einfachste wäre, deine kommandos in ein script zu packen und dieses dann per screen zu starten..

script.sh
Code:
#!/bin/bash
SOURCE=PFAD
DESTINATION=ZIELPFAD
FILE=DATEI
tmpfile=$(mktemp --suffix=VIDEO)
HandBrakeCLI optionen $SOURCE/$FILE $tmpfile
7z optionen $tmpfile $DESTINATION/$FILE
wput $DESTINATION/$FILE.* optionen
exit 0
...oder so ähnlich

und das ganze dann per screen starten
Code:
screen -dmS DEINSCRIPTNAME ./script.sh

bin da jetzt nicht so fit in sachen screen, aber so könnte es laufen ;)
 
Vor der Ausführung noch ein "chmod u+x script.sh", sonst wird nichts ausgeführt. Prinzipiell sollten Verkettungen auch funktionieren, da hast du wohl was falsch gemacht.
 
Zuletzt bearbeitet:
Verkettungen funktionieren nur innerhalb von ein und derselben Shell, screen macht aber eine neue auf. Deswegen kannst du zwar die Befehle innerhalb des screen verketten, aber nicht mit den screen-Befehlen selbst.
 
Mehrere Dateien aus Verzeichnis

Danke euch. Mein Fehler war, dass ich eben den screen immer manuell starten muss, dann funktioniert die shell, wie von euch beschrieben, so wie sie es sollte :daumen:


Ich habe jetzt öfters mehrere Video Dateien in einem Ordner, z.B.: nikon_17-09-01.mp4, nikon_17-09-02.mp4, ...
Wie kann man mehrere Dateien auf einmal als wildcard in die shell eingeben?

Code:
#!/bin/bash

SOURCE="$1"
FILE="$2"

HandBrakeCLI -i "$SOURCE/$FILE" -o "/media/freigaben/uploads/$FILE.mp4"

7z a "/media/freigaben/uploads/4ftp/$FILE.7z" "/media/freigaben/uploads/$FILE"*

wput -nd "/media/freigaben/uploads/4ftp/$FILE"* ftp://example.com/

exit 0
Wenn ich mein "script.sh /pfad/ nikon_17-09*" starte, sollen alle Dateien die dem entsprechen in einer Schleife abgearbeitet werden.
 
AW: Mehrere Dateien aus Verzeichnis

Crys schrieb:
Wenn ich mein "script.sh /pfad/ nikon_17-09*" starte, sollen alle Dateien die dem entsprechen in einer Schleife abgearbeitet werden.
Und woher soll die Schleife kommen?

Übrigens:
In $2 bzw. $FILE steht nur der 1. Dateiname. Der 2. Dateiname steht in $3 usw. Sich nur um $2 kümmern wird also nichts.

Wenn du script.sh /pfad/ "nikon_17-09*" aufrufst, also die Dateien in Quotes , steht in $2 zwar eine Liste aller Dateien, aber eine Schleife gibts dann noch immer nicht.
 
Zuletzt bearbeitet:
AW: Mehrere Dateien aus Verzeichnis

Code:
for FILES in $(ls /mnt/video); do /scripts/convert.sh ${FILES};done
for FILES in /mnt/video/video1.mpg /mnt/video2.mpg;do /scripts/convert.sh ${FILES};done
Fall 1: Alle Dateien im Verzeichnis /mnt/video
Fall 2: nur spezifizierte Dateien
 
Danke euch!

Fall 1 ist glaube ich genau was ich möchte, abgewandelt.
Code:
for FILES in $(ls /mnt/video/nikon_17-09*); do /scripts/convert.sh ${FILES};done
Jetzt habe ich nicht alle Dateien im Ordner, sondern nur die, welche ich auch möchte :)

Nur haben sich in den Dateinamen einige Leerzeichen eingemogelt, sodass im "do" FILES nicht korrekt weiter gegeben wird. Wenn ich nachfolgendes mache, klaptes es auch nicht:
Code:
for FILES in $(ls /mnt/video/nikon_17-09*); do /scripts/convert.sh "${FILES}";done
Wie escape ich das richtig, damit auch Dateinamen mit Leerzeichen richtig akzetiert werden?


Die Funktion habe ich einfachheit halber so getestet:
Code:
for FILES in $(ls "/mnt/video ordner/nikon_17-09"*); do ls -al "${FILES}";done
 
Zuletzt bearbeitet:
Crys schrieb:
Nur haben sich in den Dateinamen einige Leerzeichen eingemogelt

Code:
OLDIFS=${IFS};IFS=$(echo -en "\n\b"); for FILES in $(ls /mnt/video/ | egrep -i "^nikon_17-09" | awk '{gsub(/ /,"\\ ")}; 1'); do /scripts/convert.sh "${FILES}";done;IFS=${OLDIFS}

Mehrfaches tricksen:

Code:
IFS=$(echo -en "\n\b");
sorgt dafür, daß ein Element mit Zeilenende aufhört, nicht wie sonst üblich mit Leerzeichen. Zuvor haben wir den alten Feldtrenner als Variable gespeichert, um ihn später wieder zurücksetzen zu können.

Code:
$(ls /mnt/video/ | egrep -i "^nikon_17-09" | awk '{gsub(/ /,"\\ ")}; 1');
grep dient hier in Verbindung mit regex zum Auffinden von Dateien, die mit dem String "nikon_17-09" beginnen (-i ignoriert lediglich groß-/Kleinschreibung), awk in Verbindung mit gsub ersetzt hier alle Leerzeichen.

Denk auch daran, daß nachher in Deinem Script die übergebenen Strings passend bearbeitet werden müssen.

Crys schrieb:
Die Funktion habe ich einfachheit halber so getestet:
Wenn ich wissen will, ob ein String wie gewünscht übernommen oder gebildet wurde, nutze ich dafür zum Testen schlichtweg "echo ${VARIABLE}" in der Schleife. über "bash -x ./script.sh" kannst Du Dir auch eine Zeilenweise Abarbeitung des Scripts anzeigen lassen...
 
Crys schrieb:
Nur haben sich in den Dateinamen einige Leerzeichen eingemogelt, sodass im "do" FILES nicht korrekt weiter gegeben wird. Wenn ich nachfolgendes mache, klaptes es auch nicht:
Code:
for FILES in $(ls /mnt/video/nikon_17-09*); do /scripts/convert.sh "${FILES}";done

Probier es mal mit:
Code:
find /mnt/video/ -name "nikon_17-09*" -print0 | while read -d $'\0' f; do /scripts/converst.sh "$f"; done
 
Vielen Dank euch beiden!

Twostone schrieb:
Denk auch daran, daß nachher in Deinem Script die übergebenen Strings passend bearbeitet werden müssen.
Ich merke was du meinst, die Auskommentierungen.

Kann ich im konvertierungs Skript dann einfach gleich zu beginn den Dateinamen wieder ändern lassen!? So klappt es zumindest leider nicht:
Code:
FILE=2$ | awk '{gsub("\\ ",/ /)}; 1');


@Limit:
Deine Lösung sieht viel eleganter aus, aber leider verstehe ich nicht ganz wie das funktioinert (noch weniger). Denn ich brauche genau die Ausgabe, die bei deinem Beispiel herauskommt, aber um den Pfad reduziert. Wie mache ich das?
 
Crys schrieb:
@Limit:
Deine Lösung sieht viel eleganter aus, aber leider verstehe ich nicht ganz wie das funktioinert (noch weniger). Denn ich brauche genau die Ausgabe, die bei deinem Beispiel herauskommt, aber um den Pfad reduziert. Wie mache ich das?
Meinst du das Script soll nur mit den Dateinamen statt den kompletten Pfaden gefüttert werden? Dann probier mal:
Code:
find /mnt/video/ -name "nikon_17-09*" -print0 | while read -d $'\0' f; do /scripts/converst.sh $(basename "$f"); done
 
Vielen Dank Limit. Das ist ja extrem simpel ... wenn man weiß wie ;)

Ich sammel jetzt in Skript #1 die Dateien (ähnlich dem letzten Code) und der übergibt das dann je Datei an das Skript #2, dass vom Anfang des Threads, zum konverieren. Das passt dann auch soweit?

Vielen Dank noch mal euch allen, dass spart mir in Zukunft sehr viel klick Arbeit :daumen:
Ergänzung ()

/edit: es klappt doch nicht :mad:

Ich führe das aus:
Code:
/var/bash/mhb2ftp.sh "/video ordner" "nikon_17-09"

hb2ftp.sh:
Code:
#!/bin/bash

SOURCE="$1"
FILEX="$2"
FILE=$(basename "$FILEX" .mp4)

HandBrakeCLI -i "$SOURCE/$FILEX" -o "/media/freigaben/uploads/$FILE.mp4"

7z a "/media/freigaben/uploads/4ftp/$FILE.7z" "/media/freigaben/uploads/$FILE"*

cd /media/freigaben/uploads/4ftp/
wput -nd "$FILE"* ftp://domain.com

#break
#exit 0

mhb2ftp.sh:
Code:
#!/bin/bash

SOURCE="$1"
FILE="$2"

find "$SOURCE" -name "$FILE*" -print0 | while read -d $'\0' f; do /var/bash/hb2ftp.sh "$SOURCE" "$(basename "$f")"; done

exit 0
Jetzt wird aber nur die aller erste Datei in der Liste bearbeitet, also das Skript "hb2ftp.sh" nur einmal ausgeführt und dann alles beendet.
Anfangs dachte ich, dass es am "exit 0" lag, dass ich noch am Ende des Skriptes hatte. Das habe dich durch ein "break" getauscht, da wir ja im "mhb2ftp.sh" in einer while-Schleife sind. Dann kommt aber immer die Fehlermeldung: das man für break in einer Schleife sein muss ...

Was mache ich falsch?
 
Zuletzt bearbeitet:
Was bezweckst du mit dem ".mp4" in Zeile 5 von hb2ftp.sh? Bei mir bewirkt das garnichts.

Oder am besten beschreib mal den Workflow an einem konkreten Beispiel. Es gibt da ein, zwei Stellen in deinem Script die für mich keinen Sinn ergeben, z.B. sieht es für mich so aus, dass du jedes mal alle Dateien zum Archiv hinzufügst anstatt immer nur das eine, dass gerade bearbeitet wurde und es sieht für mich auch so aus als würdest du bei jedem Durchlauf alle Archive (auch die alten) versuchen hochzuladen.
 
Zuletzt bearbeitet:
In den weiteren Optionen von Handbrake lasse ich immer eine mp4 Datei erstellen. Weil am Dateinamen (bzw. $FILE) eh immer das Präfix noch hängt und es in den aller meisten Fällen um mp4 handelt, kürze ich es (falls vorhanden) in Zeile 5 weg.

In Zeile 9 lasse ich Archive mit je 100MB erstellen (habe ich auch der Übersichtlichkeit halber hier weg gelassen). Deshalb in Zeile 12 das Sternchen. Es wird aber jeweils nur die aktuelle Datei (video_1.mp4.7z.001, video_1.mp4.7z.002, ...) hoch geladen.

Ich glaube das war es ;)


Jetzt noch mal zum aktuellen Problem:
Wieso setzt er die Schleife aus "mhb2ftp.sh" nicht fort? Sondern behandelt nur die allererste Datei?
 
Bist du sicher, dass Handbrake mit deinen Quellen klar kommt, denn wenn Handbrake mit einem Fehler abbricht, dann bricht auch das ganze Script ab. Ich hab das Script mal durchlaufen lassen, aber weder mit Handyvideos noch mit Youtube-Videos lief Handbrake durch. Nachdem ich den Handbrake-Aufruf durch erzeugen von Dummy-Dateien ersetzt habe, lief die komplette Schleife durch.
 
Ja, das Konvertieren klappt einwandfrei ;)
Genauso wie das komprimieren und hochladen. Erst nach dem wput beendet er das Skript ohne (Fehler-) Meldung.
Die Dateien habe ich schon mehrfach erfolgreich herunter geladen, entpackt und funktionieren.
Mit genau den Skript, wie gepostet. Nur die Optionen habe ich weg gelassen (kann ich später noch mal Posten, bin gerade nur am Handy).
Wieso bricht er bei dir Handbrake ab?

Ich habe weiter probiert: Wenn ich nichts konvertiere, nur die Befehle ausgeben lasse, dann läuft auch die Schleife durch. Das dauert bei 10 Dateien aber nur 2s.
Wenn ich nur eine Datei erfolgreich konvertiere, komprimiere und hoch lade, dann braucht das 4-6h. Kann es an der langen Zeit liegen? Das er deshalb nicht die Schleife fortsetzt?
 
Handbrake bricht beim eigentlichen Encoding mit x264 ab:
x264 [info]: using SAR=1/1
x264 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 LZCNT
x264 [info]: profile High, level 5.1
ERROR: avio_open2 failed, errno -2
[..]
Encode failed (error 3).
HandBrake has exited.

Zeit spielt keine Rolle, ich hab schon ähnliche Scripte gehabt, die alle Fernsehaufnahmen vom Receiver encoded haben und das dauerte auf dem alten Rechner häufig länger als eine Woche.

Wenn er ohne die Programmaufrufe die Schleife durchläuft, dann sorgt eines der Programme für einen Abbruch, z.B. durch einen errorcode.
 
Danke, ich lasse mal einen Durchlauf per "> fehler.log 2>&1" in eine Datei schreiben, vielleicht habe ich etwas übersehen. Wenn aber auch bei der HandbrakeCLI ein error ausgegeben wurde, dann sollte das Skript doch unmittelbar abbrechen und nicht erst nach wput?
Ergänzung ()

So sieht mein Skript hb2ftp.sh aus:
Code:
#!/bin/bash

SOURCE="$1"
FILEX="$2"
FILE=$(basename "$FILEX" .mp4)

HandBrakeCLI -f mp4 -w 1136 -e x265 -q "25 -E faac -6 stereo -R 48 -B 160 -D 0.0 -x ref=2:bframes=2:subq=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0 -v 1 -i "$SOURCE/$FILEX" -o "/media/freigaben/uploads/$FILE.mp4"

7z a -mmt=on -mx=9 -v100m "/media/freigaben/uploads/4ftp/$FILE.7z" "/media/freigaben/uploads/$FILE"*

cd /media/freigaben/uploads/4ftp/
wput -nd "$FILE"* ftp://domain.com

Ich habe die Log-Datei vom letzten Skript noch einmal genau angeschaut und da kommt kein einziger (echter) Fehler vor: https://pastebin.com/5Xp5TYci

Das hb2ftp.sh Skript funktioniert auch weiterhin einwandfrei, nur eben nicht in der Schleife.

mhb2ftp.sh:
Code:
#!/bin/bash

SOURCE="$1"
FILE="$2"

find "$SOURCE" -name "$FILE*" -print0 | while read -d $'\0' f; do /var/bash/hb2ftp.sh "$SOURCE" "$(basename "$f")"; done

exit 0

Ich habe absolut keine Ahnung mehr, wo ich suchen soll :(
 
Crys schrieb:
Ich habe absolut keine Ahnung mehr, wo ich suchen soll

Die Übergabe wird nicht passen, das aus der Schleife aufgerufene Script interpretiert Leerzeichen als Beginn eines neuen Parameters. Ersetze "#!/bin/bash" durch "#!/bin/bash -x". Schau Dir den Output an. Kannst auch stattdessen mal einfach statt script echo ${SOURCE}; echo $(basename "${FILE}") ausführen lassen.
 
Zuletzt bearbeitet:
Zurück
Oben