it-swarm.com.de

Der schnellste Weg, um Dateien zu verketten

Ich habe mehr als 10.000 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.

26
fsperrle

Nein, Katze ist sicherlich der beste Weg, dies zu tun. Warum sollten Sie python] verwenden, wenn zu diesem Zweck bereits ein Programm in C geschrieben wurde? Sie sollten jedoch die Verwendung von xargs in Betracht ziehen, falls die Befehlszeilenlänge ARG_MAX Und Sie benötigen mehr als ein cat. Mit GNU Tools) entspricht dies dem, was Sie bereits haben:

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z |
  xargs -0 cat -- >>out
30
Graeme

Das erstmalige Zuweisen des Speicherplatzes für die Ausgabedatei kann die Gesamtgeschwindigkeit verbessern, da das System die Zuweisung 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 die Kopie nicht versucht wird, wenn nicht genügend freier Speicherplatz vorhanden ist.

Wenn auf btrfs, könnten Sie copy --reflink=always die erste Datei (die keine Datenkopie impliziert und daher fast augenblicklich wäre) und den Rest anhängen. Wenn es 10000 Dateien gibt, macht das wahrscheinlich keinen großen Unterschied, es sei denn, die erste Datei ist sehr groß.

Es gibt eine API, die das verallgemeinert, um alle Dateien erneut zu kopieren (das BTRFS_IOC_CLONE_RANGEioctl), aber ich konnte kein Dienstprogramm finden, das diese API verfügbar macht. Sie müssten dies also in C (oder python oder anderen Sprachen tun, vorausgesetzt, sie können beliebige ioctls).

Wenn die Quelldateien spärlich sind oder große Sequenzen von NUL-Zeichen enthalten, können Sie eine spärliche Ausgabedatei erstellen (was Zeit und Speicherplatz spart) mit (on GNU Systems):

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z | xargs -r0 cat | cp --sparse=always /dev/stdin out
22