Benötigen Sie Expertenvorschläge zum folgenden Vergleich:
Codesegment mit Schleife:
for file in `cat large_file_list`
do
gzip -d $file
done
Codesegment mit einfacher Erweiterung:
gzip -d `cat large_file_list`
Welches wird schneller sein? Müssen große Datenmengen manipulieren.
linux
bash
shell-script
shell
Leon
quelle
quelle
gzip
auf Ihrem System dauert, wie viele Dateien in der Dateiliste enthalten sind und wie groß diese Dateien sind.xargs gzip -d < large_file_list
,tr \\n \\0 large_file_list | xargs -0 gzip -d
Antworten:
Komplikationen
Folgendes funktioniert nur manchmal:
Drei Probleme sind (in
bash
und den meisten anderen Bourne-ähnlichen Muscheln):Es schlägt fehl, wenn ein Dateiname Leerzeichen oder Zeilenumbrüche enthält (vorausgesetzt, er
$IFS
wurde nicht geändert). Dies liegt an der Wortteilung der Shell .Es kann auch fehlschlagen, wenn ein Dateiname globaktive Zeichen enthält. Dies liegt daran, dass die Shell die Pfadnamenerweiterung auf die Dateiliste anwendet .
Es schlägt auch fehl, wenn Dateinamen mit beginnen
-
(wenn diesPOSIXLY_CORRECT=1
nur für die erste Datei gilt) oder wenn ein Dateiname vorhanden ist-
.Es schlägt auch fehl, wenn zu viele Dateinamen darin sind, um in eine Befehlszeile zu passen.
Der folgende Code unterliegt denselben Problemen wie der obige Code (mit Ausnahme des vierten).
Zuverlässige Lösung
Wenn Sie
large_file_list
genau einen Dateinamen pro Zeile haben und eine aufgerufene Datei-
nicht dazu gehört und Sie sich auf einem GNU-System befinden, verwenden Sie:-d'\n'
weistxargs
an, jede Eingabezeile als separaten Dateinamen zu behandeln.-r
weistxargs
an, den Befehl nicht auszuführen, wenn die Eingabedatei leer ist.--
weist darauf hin,gzip
dass die folgenden Argumente nicht als Optionen behandelt werden sollen, selbst wenn sie mit beginnen-
.-
allein würde trotzdem als-
anstelle der aufgerufenen Datei behandelt-
.xargs
Es werden viele Dateinamen in jede Befehlszeile eingefügt, jedoch nicht so viele, dass das Befehlszeilenlimit überschritten wird. Dies reduziert die Häufigkeit, mit der eingzip
Prozess gestartet werden muss, und macht dies daher schnell. Es ist auch sicher: Die Dateinamen werden auch vor Wortteilung und Pfadnamenerweiterung geschützt .quelle
for
Schleife wird bei weitem die langsamste sein. Die beiden anderen Methoden sind sehr nahe beieinander.xargs
: Zumindest die GNU-Version verfügt über eine--arg-file
Option (Kurzform-a
). Also könnte man esxargs -a large_file_list -rd'\n' gzip -d
stattdessen tun . Tatsächlich gibt es keinen Unterschied, abgesehen von der Tatsache, dass<
es sich um einen Shell-Operator handelt, derxargs
von stdin lesen würde (welche Shell "verlinkt"), während-a
diexargs
parallel
zum Ausführen mehrerer Kopien vongzip
, aberxargs
(zumindest die GNU- Kopie ) hat auch dafür den-P
Schalter. Auf Multicore-Computern kann dies einen Unterschied machen. Es ist aber auch möglich, dass die Dekomprimierung ohnehin vollständig E / A-gebunden ist.Ich bezweifle, dass es viel ausmachen würde.
Ich würde eine Schleife verwenden, nur weil ich nicht weiß, wie viele Dateien in der Listendatei aufgeführt sind, und ich (im Allgemeinen) nicht weiß, ob einer der Dateinamen Leerzeichen in seinen Namen hat. Eine Befehlsersetzung, die eine sehr lange Liste von Argumenten erzeugen würde, kann zu einem Fehler "Argumentliste zu lang" führen, wenn die Länge der generierten Liste zu lang ist.
Meine Schleife würde so aussehen
Dies würde mir zusätzlich erlauben, Befehle zum Verarbeiten der Daten nach dem
gunzip
Befehl einzufügen . Abhängig davon, was die Daten tatsächlich sind und was damit zu tun ist, kann es sogar möglich sein, sie zu verarbeiten, ohne sie in einer Datei zu speichern:(Wo
process_data
ist eine Pipeline, die die unkomprimierten Daten von der Standardeingabe liest?)Wenn die Verarbeitung der Daten länger dauert als die Dekomprimierung, ist die Frage, ob eine Schleife effizienter ist oder nicht, irrelevant.
Im Idealfall würde ich es jedoch vorziehen, eine Liste von Dateinamen nicht zu bearbeiten und stattdessen ein Dateinamen-Globbing-Muster wie in zu verwenden
Wo
./*.gz
ist ein Muster, das mit den relevanten Dateien übereinstimmt. Auf diese Weise sind wir weder von der Anzahl der Dateien noch von den in den Dateinamen verwendeten Zeichen abhängig (sie können Zeilenumbrüche oder andere Leerzeichen enthalten oder mit Bindestrichen usw. beginnen).Verbunden:
quelle
Von diesen beiden ist die mit allen Dateien, die an einen einzelnen Aufruf von übergeben wurden,
gzip
wahrscheinlich schneller, genau weil Sie nurgzip
einmal starten müssen . (Das heißt, wenn der Befehl überhaupt funktioniert, lesen Sie die anderen Antworten für die Vorbehalte.)Aber ich möchte an die goldene Regel der Optimierung erinnern : Tun Sie es nicht vorzeitig.
Optimieren Sie so etwas nicht, bevor Sie wissen, dass es ein Problem ist.
Dauert dieser Teil des Programms lange? Das Dekomprimieren großer Dateien könnte dazu führen, dass Sie es trotzdem tun müssen, sodass die Beantwortung möglicherweise nicht so einfach ist.
Messen. Wirklich, es ist der beste Weg, um sicher zu sein.
Sie sehen die Ergebnisse mit Ihren eigenen Augen (oder mit Ihrer eigenen Stoppuhr) und sie gelten für Ihre Situation, die zufällige Antworten im Internet möglicherweise nicht bieten. Fügen Sie beide Varianten in Skripte ein und führen Sie
time script1.sh
und austime script2.sh
. (Führen Sie dies mit einer Liste leerer komprimierter Dateien durch, um den absoluten Overhead zu messen.)quelle
Wie schnell ist deine Festplatte?
Dies sollte alle Ihre CPUs verwenden:
Ihr Limit wird also wahrscheinlich die Geschwindigkeit Ihrer Festplatte sein.
Sie können versuchen, sich anzupassen mit
-j
:Dadurch wird die Hälfte der Jobs wie beim vorherigen Befehl parallel ausgeführt und Ihre Festplatte wird weniger belastet. Abhängig von Ihrer Festplatte kann dies schneller sein.
quelle