2016-04-02 3 views
0

Ich habe dieses kleine Skript, um Bilder von einer bestimmten Liste in einer Datei herunterladen.Parallele WGET-Download in Bash-Skript

FILE=./img-url.txt 
while read line; do 
url=$line 
wget -N -P /images/ $url 
wget -N -P /images/ ${url%.jpg}_{001..005}.jpg 
done < $FILE 

Das Problem ist, dass es zu lange läuft (> 5000 Zeilen in der Datei). Gibt es eine Möglichkeit, die Dinge zu beschleunigen? Teilen Sie die Quelle txt in separate Dateien auf und führen Sie mehrere wget-Instanzen gleichzeitig aus.

+1

Relevant: [Parallel wget in Bash] (https://stackoverflow.com/questions/7577615/parallel-wget-in-bash) – jDo

Antwort

2

Es gibt eine Reihe von Möglichkeiten, dies zu tun. GNU Parallel wäre die allgemeinste Lösung, aber wenn man bedenkt, wie Sie Ihre Frage gestellt haben, ja, teilen Sie die Datei in Teile und führen Sie das Skript gleichzeitig auf jedem Teil aus. Wie viele Teile die Datei teilen soll, ist eine interessante Frage. 100 Stück würden bedeuten, dass 100 wget-Prozesse gleichzeitig erzeugt werden. Fast alle dieser Geräte werden im Leerlauf betrieben, während nur sehr wenige die gesamte Netzwerkbandbreite nutzen. Ein Prozess könnte die gesamte Bandbreite für eine Stunde nutzen, aber ich denke, ein guter Kompromiss besteht darin, die Datei in vier Dateien aufzuteilen, sodass vier wget-Prozesse gleichzeitig ausgeführt werden. Ich werde dein Skript geturls.sh aufrufen. Geben Sie dies in der Befehlszeile ein.

split -l 4 img-url.txt 
for f in xaa xab xac xad; do 
    ./geturls.sh $f & 
done 

Dies teilt Ihre Datei in vier ~ gleichmäßige Stücke. Die geteilten Befehlsausgabedateien erhalten standardmäßig einige einfache Dateinamen, in diesem Fall xaa, xab usw. Die for-Schleife nimmt die Namen dieser Teile und gibt sie an geturl.sh als Kommandozeilenargument, das erste auf der Befehlszeile nach dem Programmnamen. Die geturls.sh wird in den Hintergrund gesetzt (&), so dass die nächste Iteration der Schleife sofort passieren kann. Auf diese Weise wird geturls.sh praktisch gleichzeitig auf allen vier Teilen der Datei ausgeführt, sodass Sie vier wget-Prozesse gleichzeitig ausführen können.

Der Inhalt geturls.sh ist

#!/bin/bash 
FILE=$1 
while read line; do 
url=$line 
wget -N -P /images/ $url 
wget -N -P /images/ ${url%.jpg}_{001..005}.jpg 
done < $FILE 

Die einzige Änderung, die ich an Ihrem Code hat die ausdrückliche Erklärung der Schale war (aus Gewohnheit meistens) und auch, dass FILE nun den Wert in der zugeordnet ist $ 1 Variable. Denken Sie daran, dass $ 1 das (erste) Befehlszeilenargument ist, das hier der Name eines der Teile Ihrer Datei img-url.txt ist.

+0

Perfekt, aber -l-Schalter sollte -n Schalter in Ihrem Code sein. Ich kann kein Zeichen in deinem Code bearbeiten. – Adrian

+0

noch eine Frage: Das Skript wird am Ende nicht beendet. Wo sollte ich den Befehl "exit 0" eingeben? Ich habe es vorher versucht (beides), aber es hilft nicht. – Adrian

+0

Scheint so, als ob -n und -l dasselbe tun würden, aber ich werde dein Wort dafür nehmen. :) Der Befehl "exit 0" ist überflüssig. Wenn ein Skript nach unten geht, wird die Standardannahme korrekt ausgeführt. Aber wenn es einen Nicht-Null-Exit-Status gibt, sollten Sie darüber Bescheid wissen. Also setze Ausgang 0 ... Ich kann mir keinen guten Grund vorstellen. Ich meine, wenn es ein Problem gäbe, würde das Setzen von Ausgang 0 das verdecken. Sie möchten immer, dass der Exit-Status nützliche Informationen liefert, wenn möglich. Was nicht immer einfach ist. Wenn Sie es jedoch jedes Mal auf einen einzelnen Wert setzen, entfällt diese Möglichkeit. –