Schnellster Weg, um Dateien zu verketten

25

Ich habe mehr als 10k-Dateien mit insgesamt über 20 GB, die ich zu einer Datei verketten muss.

Gibt es einen schnelleren Weg als

cat input_file* >> out

?

Der bevorzugte Weg wäre ein Bash-Befehl, Python ist auch akzeptabel, wenn nicht wesentlich langsamer.

fsperrle
quelle
Aktualisiert meine Antwort, findsortiert Dateien nicht wie ein Shell-Glob.
Graeme
5
Alle (vernünftigen) Lösungen haben hier die gleiche Geschwindigkeit, da die Zeit bei 99% System-E / A liegt.
Goldlöckchen
3
Erwägen Sie, die verkettete Datei auf eine andere Festplatte zu schreiben als die, von der Sie lesen.
Luis
1
Es ist schneller, wenn outes sich auf einer anderen Festplatte befindet.

Antworten:

30

Nein, Katze ist sicherlich der beste Weg, dies zu tun. Warum sollte man Python verwenden, wenn für diesen Zweck bereits ein Programm in C geschrieben ist? Möglicherweise möchten Sie jedoch die Verwendung xargsin Betracht ziehen, wenn die Befehlszeilenlänge überschritten wird ARG_MAXund Sie mehr als eine benötigen cat. Mit GNU-Werkzeugen entspricht dies dem, was Sie bereits haben:

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z |
  xargs -0 cat -- >>out
Graeme
quelle
1
Können Sie in diesem Fall sicherstellen, dass Ihre Dateien in der angegebenen Reihenfolge gelesen werden?
Kiwy
1
Ja, weil der Ausgang von finddurchgeleitet wird sort. Ohne dies würden die Dateien in einer beliebigen Reihenfolge aufgelistet (definiert durch das Dateisystem, das die Reihenfolge der Dateierstellung sein könnte).
Scai
@scai Ich vermisse es, sorry, mit Art ist es ziemlich offensichtlich
Kiwy
1
@ Kiwy, der einzige Fall, den ich sehen kann, ist, wenn das Gebietsschema in der Umgebung nicht richtig eingestellt ist, dann verhält sich die Sortierung möglicherweise anders als bei einem bashGlob. Ansonsten sehe ich keine Fälle, in denen xargsoder catwürde sich nicht wie erwartet verhalten.
Graeme
3
@MarcvanLeeuwen xargsruft nach catBedarf auf, um einen E2BIG-Fehler von execve (2) zu vermeiden.
Stéphane Chazelas
21

Das Zuweisen des Speicherplatzes für die Ausgabedatei als Erstes kann die Gesamtgeschwindigkeit verbessern, da das System die Zuordnung nicht bei jedem Schreibvorgang aktualisieren muss.

Zum Beispiel, wenn unter Linux:

size=$({ find . -maxdepth 1 -type f -name 'input_file*' -printf '%s+'; echo 0;} | bc)
fallocate -l "$size" out &&
  find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z | xargs -r0 cat 1<> out

Ein weiterer Vorteil ist, dass der Kopiervorgang nicht ausgeführt wird, wenn nicht genügend freier Speicherplatz vorhanden ist.

Wenn diese Option aktiviert ist btrfs, können Sie copy --reflink=alwaysdie erste Datei (die keine Datenkopie impliziert und daher fast augenblicklich ist) und den Rest anhängen. Wenn es 10000 Dateien gibt, wird das wahrscheinlich keinen großen Unterschied machen, es sei denn, die erste Datei ist sehr groß.

Es gibt eine API, um das zu verallgemeinern, um alle Dateien (die BTRFS_IOC_CLONE_RANGE ioctl) erneut zu kopieren , aber ich konnte kein Hilfsprogramm finden, das diese API verfügbar macht, also müssten Sie es in C ( pythonoder in einer anderen Sprache, vorausgesetzt, sie können beliebige ioctls aufrufen ) .

Wenn die Quelldateien spärlich sind oder große Sequenzen von NUL-Zeichen enthalten, können Sie mit (auf GNU-Systemen) eine spärliche Ausgabedatei erstellen (um Zeit und Speicherplatz zu sparen):

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z | xargs -r0 cat | cp --sparse=always /dev/stdin out
Stéphane Chazelas
quelle
1
@XTian, ​​nein, es sollte weder >noch sein >>, aber 1<>wie gesagt in die Datei schreiben .
Stéphane Chazelas
5
@grebneke <>ist der Standard-Bourne / POSIX-Umleitungsoperator für Lesen und Schreiben. Einzelheiten finden Sie in Ihrem Shell-Handbuch oder in der POSIX-Spezifikation . Die Standardeinstellung fdist 0für den <>Operator ( <>ist kurz für 0<>, wie <ist kurz für 0<und >kurz für 1>), daher müssen Sie die 1stdout explizit umleiten. Hier ist es nicht so sehr so, dass wir read + write ( O_RDWR) benötigen , aber dass wir nicht wollen O_TRUNC(wie in >), dass die Zuordnung aufgehoben wird, was wir gerade zugewiesen haben.
Stéphane Chazelas
1
@grebneke, unix.stackexchange.com/search?q=user%3A22565+%22%3C%3E%22 gibt Ihnen einige davon. ksh93 hat BTW-Suchoperatoren, und Sie können mit ddoder über Lesen vorwärts suchen .
Stéphane Chazelas
1
@StephaneChazelas - vielen Dank für Ihre Hilfe und Ihr Wissen!
Grebneke
1
Ich bin nicht davon überzeugt, dass es viele Fälle geben wird, in denen fallocateder Overhead der zusätzlichen Kosten zunichte gemacht wird find, auch wenn er beim zweiten Mal schneller sein wird. btrfssicherlich eröffnet sich aber einige interessante möglichkeiten.
Graeme