2017-08-23 4 views
2

Ich habe mehrere Fragen zu diesem Thema gesehen, aber mir fehlt die Fähigkeit, dies zu meinem spezifischen Problem zu übersetzen. Ich habe eine for-Schleife, die Unterverzeichnisse durchläuft und dann ein .sh-Skript für eine komprimierte Textdatei in jedem Verzeichnis ausführt. Ich möchte diesen Prozess parallelisieren, aber ich bemühe mich, Gnu parallel anzuwenden.Gnu parallel zu einer For-Schleife zu parallelisieren

Hier ist meine Schleife:

for d in ./*/ ; do (cd "$d" && script.sh); done 

ich, dass ich zur Eingabe einer Liste in parallele müssen verstehen, so habe ich das versucht:

ls -d */ | parallel cd && script.sh 

Während dies zu beginnen scheint, ich ein Fehler, wenn gzip versucht, eine der txt-Dateien in dem Verzeichnis zu entpacken, dass die Datei nicht existiert:

gzip: *.txt.gz: No such file or directory 

Wenn ich jedoch das Original for-Schleife verwende, habe ich keine Probleme, abgesehen davon, dass es ein Jahrhundert dauert, bis es fertig ist. Außerdem erhalte ich den gzip-Fehler nur einmal, wenn ich parallel benutze, was so merkwürdig ist, wenn man bedenkt, dass ich über 1000 Unterverzeichnisse habe.

Meine Fragen sind:

  1. Wie erhalte ich Parallel in meinem Fall zu arbeiten? Wie bekomme ich parallel dazu, die Anwendung eines .sh-Skripts auf Tausende von Dateien in ihren eigenen Unterverzeichnissen zu parallelisieren? dh - was ist die Lösung für mein Problem? Ich muss Fortschritte machen.

  2. Was fehlt mir? Syntax, Schleife, schlechtes Skript? Ich will lernen.

  3. Wird parallel versucht, alle diese .sh-Skripts parallel auszuführen? Warum bekomme ich keinen Fehler für jede .txt.gz Datei?

  4. Ist parallel die beste Option für die Anwendung? Gibt es eine andere Option, die besser zu meinen Bedürfnissen passt?

Antwort

4

Zwei Probleme:

  1. In:

    ls -d */ | parallel cd && script.sh 
    

    was parallel ist nur cd, nicht script.sh. script.sh wird nur einmal ausgeführt, nachdem alle parallel cd Jobs ausgeführt wurden, wenn kein Fehler aufgetreten ist. Es ist das gleiche wie:

    ls -d */ | parallel cd 
    if [ $? -eq 0 ]; then script.sh; fi 
    
  2. Sie haben nicht das Zielverzeichnis cd passieren. Also, was von parallel ausgeführt wird, ist nur cd, die nur das aktuelle Verzeichnis in Ihr Home-Verzeichnis ändert. Das letzte script.sh wird im aktuellen Verzeichnis ausgeführt (von wo Sie den Befehl aufgerufen haben), wo es wahrscheinlich keine *.txt.gz Dateien gibt, daher der Fehler.

Sie können selbst überprüfen, um die Wirkung des ersten Problems mit:

$ mkdir /tmp/foobar && cd /tmp/foobar && mkdir a b c 
$ ls -d */ | parallel cd && pwd 
/tmp/foobar 

Der Ausgang der pwd wird nur einmal gedruckt, auch wenn Sie mehr als ein Eingangsverzeichnis hat. Sie können das Problem beheben, indem Sie den Befehl unter Angabe und prüfen Sie dann das zweite Problem mit:

$ ls -d */ | parallel 'cd && pwd' 
/homes/myself 
/homes/myself 
/homes/myself 

Sie sollten so viele pwd Ausgänge sehen, wie es Eingangsverzeichnisse sind, aber es ist immer die gleiche Ausgabe: Ihr Home-Verzeichnis. Sie können das zweite Problem beheben, indem Sie die Ersatzzeichenfolge {} verwenden, die durch die aktuelle Eingabe ersetzt wird. Überprüfen Sie es mit:

$ ls -d */ | parallel 'cd {} && pwd' 
/tmp/foobar/a 
/tmp/foobar/b 
/tmp/foobar/c 

Jetzt sollten Sie alle Eingabe-Verzeichnisse ordnungsgemäß in der Ausgabe aufgeführt haben.

Für Ihr spezielles Problem sollte diese Arbeit:

ls -d */ | parallel 'cd {} && script.sh' 
+0

Schön erklärt! –