Was ist der beste Weg, um Dateien nach dem Teilen wieder zusammenzufügen?

73

Wenn ich eine große Datei habe und sie in 100-Megabyte-Blöcke aufteilen muss, mache ich das

split -b 100m myImage.iso

Das gibt mir normalerweise sowas

xaa
xab
xac
xad

Und um sie wieder zusammenzubringen, habe ich benutzt

cat x* > myImage.iso

Es scheint, als gäbe es eine effizientere Möglichkeit, als jede Codezeile in einer Gruppe von Dateien zu lesen catund die Ausgabe in eine neue Datei umzuleiten. So öffnen Sie einfach zwei Dateien, entfernen die EOFMarkierung von der ersten und verbinden sie - ohne den gesamten Inhalt durchgehen zu müssen.

Windows / DOS verfügt über einen Kopierbefehl für Binärdateien. In der Hilfe wird erwähnt, dass dieser Befehl so konzipiert wurde, dass mehrere Dateien kombiniert werden können. Es funktioniert mit dieser Syntax: ( /bist für den Binärmodus)

copy /b file1 + file2 + file3 outputfile

Gibt es eine ähnliche oder bessere Möglichkeit, große Dateien unter Linux zusammenzuführen als cat?

Aktualisieren

Es scheint, dass dies cattatsächlich der richtige und beste Weg ist, Dateien zusammenzufügen. Ich bin froh zu wissen, dass ich die ganze Zeit den richtigen Befehl verwendet habe :) Vielen Dank an alle für Ihr Feedback.

cwd
quelle
22
Randnotiz: Besser nicht verwenden cat x*, da die Reihenfolge der Dateien von Ihren Ländereinstellungen abhängt. Beginnen Sie besser mit der Eingabe cat x, als Esc und dann zu drücken *- Sie sehen die erweiterte Reihenfolge der Dateien und können sie neu anordnen.
rozcietrzewiacz
16
Stattdessen können cat x*Sie die Erweiterung cat xa{a..g}der Shell-Klammer in Betracht ziehen, wodurch die angegebene Sequenz auf cat xaa xab xac xad xae xaf xag
Peter.O
3
@rozcietrzewiacz - können Sie ein Beispiel dafür geben, wie ich meine Ländereinstellung anpassen würde, die nicht funktioniert cat x*? Würde sich die neue Ländereinstellung nicht auch darauf auswirken split, dass sie immer funktionieren würden , wenn splitund cat x*auf demselben System verwendet würden?
KWD
3
"Öffnen Sie zwei Dateien, entfernen Sie den EOF-Marker vom ersten und verbinden Sie sie - ohne den gesamten Inhalt durchgehen zu müssen." ... klingt, als müssten Sie ein neues Dateisystem erfinden, um das zu tun, was Sie wollen
JoelFan
6
@cwd: Betrachten split.cin GNU Coreutils werden die Suffixe aus einer festen Anordnung von Zeichen aufgebaut: static char const *suffix_alphabet = "abcdefghijklmnopqrstuvwxyz";. Das Suffix würde vom Gebietsschema nicht beeinflusst. (Aber ich glaube nicht, dass ein vernünftiges Gebietsschema die Kleinbuchstaben neu anordnen würde; selbst EBCDIC behält ihre Standardreihenfolge bei.)
Keith Thompson,

Antworten:

50

Dafür catwurde es gemacht. Da es eines der ältesten GNU-Tools ist, halte ich es für sehr unwahrscheinlich, dass ein anderes Tool dies schneller / besser macht. Und es ist nicht kochend - es ist nur dann ausgegeben , umgeleitet werden .

rozcietrzewiacz
quelle
Der cat x, then press EscTrick, den Sie erwähnt haben, ist ordentlich. Ich habe nach so etwas gesucht, danke. Guter Kommentar und gute Antwort
Peter.O
2
Gern geschehen :) Wenn Sie diese Dateiliste in der Befehlszeile haben, können Sie Ctrl+Wauch ein Wort ausschneiden und dann Ctrl+Yeinfügen.
rozcietrzewiacz
cat bedeutet "verketten"
JoelFan
4
.. and "catenate" leitet sich von einem lateinischen Wort "catena" ab, was "eine Kette" bedeutet. Verketten bedeutet , die Glieder einer Kette zusammenzufügen. ... (und etwas abseits des Themas leitet sich auch eine Fahrleitungskurve von "catena" ab. So hängt eine Kette)
Peter.O
19

Unter der Haube

Es gibt keinen effizienteren Weg, als die erste Datei zu kopieren und danach die zweite Datei zu kopieren und so weiter. DOS copyund cattun das.

Jede Datei wird unabhängig von anderen Dateien auf der Festplatte gespeichert. Nahezu jedes Dateisystem, das zum Speichern von Daten auf einem plattenähnlichen Gerät entwickelt wurde, arbeitet blockweise. Hier ist eine stark vereinfachte Darstellung dessen, was passiert: Die Festplatte ist in Blöcke von beispielsweise 1 KB unterteilt, und für jede Datei speichert das Betriebssystem die Liste der Blöcke, aus denen sie besteht. Die meisten Dateien sind nicht ganzzahlig lang, sodass der letzte Block nur teilweise belegt ist. In der Praxis weisen Dateisysteme viele Optimierungen auf, z. B. das Teilen des letzten Teilblocks zwischen mehreren Dateien oder das Speichern von "Blöcken 46798 bis 47913" anstelle von "Block 46798, Block 46799, ...". Wenn das Betriebssystem eine neue Datei erstellen muss, sucht es nach freien Blöcken. Die Blöcke müssen nicht aufeinander folgen: Wenn nur die Blöcke 4, 5, 98 und 178 frei sind, können Sie trotzdem eine 4-KB-Datei speichern.

Sie könnten Teilblöcke in der Mitte einer Datei unterstützen, dies würde jedoch zu einer erheblichen Komplexität führen, insbesondere wenn Sie nicht sequentiell auf Dateien zugreifen: Um zum 10340. Byte zu springen, könnten Sie nicht mehr zum 100. Byte des 11. Blocks springen um die Länge jedes dazwischenliegenden Blocks zu überprüfen.

Bei Verwendung von Blöcken können Sie nicht einfach zwei Dateien verbinden, da die erste Datei im Allgemeinen in der Mitte des Blocks endet. Sicher, Sie könnten einen Sonderfall haben, aber nur, wenn Sie beide Dateien bei der Verkettung löschen möchten. Das wäre eine sehr spezifische Behandlung für eine seltene Operation. Eine solche spezielle Behandlung funktioniert nicht von alleine, da auf einem typischen Dateisystem auf viele Dateien gleichzeitig zugegriffen wird. Wenn Sie also eine Optimierung hinzufügen möchten, müssen Sie sorgfältig überlegen: Was passiert, wenn ein anderer Prozess eine der beteiligten Dateien liest? Was passiert, wenn jemand versucht, A und B zu verketten, während jemand A und C verkettet? Und so weiter. Alles in allem wäre diese seltene Optimierung eine enorme Belastung.

Alles in allem können Sie das Zusammenfügen von Dateien nicht effizienter gestalten, ohne an anderer Stelle größere Opfer zu bringen. Es lohnt sich nicht.

Aufteilen und Verbinden

splitund catsind einfache Möglichkeiten zum Teilen und Verbinden von Dateien. splitkümmert sich um das Erstellen von Dateien mit alphabetischem Namen, damit cat *sie zusammengefügt werden können.

Ein Nachteil des catVerbindens ist, dass es nicht robust gegen häufige Fehlermodi ist. Wenn eine der Dateien abgeschnitten ist oder fehlt, catwerden Sie nicht beschweren, sondern nur eine beschädigte Ausgabe erhalten.

Es gibt Komprimierungsdienstprogramme, die mehrteilige Archive erstellen, z. B. zipsplitund rar -v. Sie sind nicht sehr unixy, weil sie zusätzlich zum Teilen komprimieren und packen (mehrere Dateien zu einer zusammenfügen) (und umgekehrt zusätzlich zum Verbinden entpacken und dekomprimieren). Sie sind jedoch nützlich, um zu überprüfen, ob Sie alle Teile haben und ob die Teile vollständig sind.

Gilles
quelle
8

Es scheint, als gäbe es einen effizienteren Weg, als den gesamten Inhalt durch das System zu stdinleiten.stdout

Nur dass das nicht wirklich passiert. Die Shell verbindet das stdout von cat direkt mit der geöffneten Datei, was bedeutet, dass "stdout durchlaufen" dasselbe ist wie auf die Festplatte schreiben.

Ignacio Vazquez-Abrams
quelle
Ich habe mir nur vorgestellt, wie man mit cat mehrere Gigabyte Code in der Konsole anzeigt, dann aufzeichnet und in eine Datei schreibt. Das ist das mentale Bild, das ich für das habe, was passieren muss, wenn ich cat benutze und die Ausgabe umleitung, die ich nicht sehen kann. Es schien nur so, als gäbe es eine Möglichkeit, zwei Dateien zu öffnen, sie zu verbinden und dann zu schließen. Das wäre effizienter, als alle Codezeilen mit zu durchlaufen cat. Vielen Dank, dass Sie mich über die direkte Verbindung informiert haben.
KWD
@cwd Es wäre möglich, ein Dateisystem zu entwerfen, in dem Sie zwei Dateien auf diese Weise verbinden könnten, aber das würde das Design des Dateisystems immens erschweren. Sie würden für diese eine Operation optimieren, um eine Menge üblicher Aufgaben komplizierter und langsamer zu machen.
Gilles
@Gilles - es wäre interessant, mehr über die Details auf niedriger Ebene zu erfahren. Das Lesen aller Sektoren von der Festplatte für mehrere Dateien und das anschließende Zurückspeichern in andere nicht verwendete Sektoren auf der Festplatte erscheint mir ineffizient. Und ich denke, große Dateien müssen manchmal in mehreren Blöcken freier Sektoren gespeichert werden, da möglicherweise nicht immer genügend Blöcke nebeneinander vorhanden sind, um sie zu speichern. Daher können Sie theoretisch Dateien zu einer zusammenfügen, indem Sie die EOF-Markierung entfernen und am Anfang der nächsten Datei auf eine Sektorgruppe zeigen. * nix ist mächtig, also habe ich mich gefragt, ob es einen besseren Weg als cat gibt.
KWD
@cwd Es gibt keinen "EOF-Marker". Kein vernünftiges modernes Dateisystem funktioniert so, weil es verhindert, dass einige Zeichen in Dateien vorkommen (oder komplexe Codierungen erfordern). Aber selbst wenn es einen EOF-Marker gäbe, hätten Sie die meiste Zeit nicht die richtige Datei danach.
Gilles
Ich meinte das Konzept des EOF-Markers und keinen tatsächlichen EOF-Marker. Ansonsten, wenn Sie sich die Bits und Bytes einer Datei auf der Festplatte ansehen, woher wissen Sie, wo sie endet? Geben Sie die Länge der Datei am Anfang an? Ich spreche von einem wirklich niedrigen Level. Ist es das, worauf Sie sich auch beziehen?
KWD
3

Ich hatte einmal genau dieses Problem: Ich wollte einige Dateien zusammenfügen, hatte aber nicht genug Speicherplatz, um sie doppelt zu speichern.

Also schrieb ich eine Reihe von Programmen:

  • man "saugt" eine Datei auf, indem man sie liest, sie an stdout sendet und, wenn fertig, sie entfernt
  • und eine, um Daten "on the fly" zu puffern.

Dies ermöglichte es mir, so etwas zu tun

partto sourcefile | mybuffer 128M >>cumufile

und so die Quelldatei zu entfernen, während 128M noch ungeschrieben war. Ein bisschen gefährlich, aber wenn die Daten nicht so wertvoll sind oder auch woanders existieren, ist das machbar.

Bei Bedarf kann ich die Quelle zur Verfügung stellen.

glglgl
quelle
0

Technisch gesehen ist dies eine Möglichkeit, auf die gesamte Datei zuzugreifen, ohne den gesamten Inhalt lesen und schreiben zu müssen. Dies kann nützlich sein, wenn große Dateien vorhanden sind oder nur noch wenig Speicherplatz zur Verfügung steht:

$ mkfifo myImage.iso
$ cat xa{a..g} > myImage.iso &

Und dann myImage.isozum Beispiel verwenden

$ md5sum myImage.iso

Obwohl es sich natürlich myImage.isoum eine spezielle Datei (Named Pipe) und nicht um eine reguläre Datei handelt, kann dies von Nutzen sein oder auch nicht, je nachdem, was Sie versuchen.

Golimar
quelle
0

Aufteilen von Dateien

Nach Größe aufteilen

Wenn Sie große Dateien in kleine Dateien aufteilen und den Namen und die Größe kleiner Ausgabedateien auswählen möchten, ist dies der richtige Weg.

split -b 500M videos\BigVideoFile.avi SmallFile.

Auf diese Weise können Sie eine große Datei in kleinere Teile von 500 MB aufteilen. Außerdem möchten Sie, dass die Namen der Teiledateien SmallFile sind. Beachten Sie, dass Sie einen Punkt nach dem Dateinamen benötigen . Das Ergebnis sollte die Erzeugung neuer Dateien sein:

SmallFile.ab SmallFile.ad SmallFile.af SmallFile.ah SmallFile.aj
SmallFile.aa SmallFile.ac SmallFile.ae SmallFile.ag SmallFile.ai SmallFile.ak
...

Nach Anzahl der Zeilen teilen

Auf diese Weise teilen Sie Textdateien in kleinere Dateien auf, die auf 50 Zeilen begrenzt sind.

split -l 50 text_to_split.txt

Das Ergebnis sollte ungefähr so ​​aussehen:

xaa xab xac ...

Nach Bytes teilen

In kleine Dateien mit einer benutzerdefinierten Größe von kleinen Dateien in Bytes aufteilen:

split -b 2048 BigFile.mp4

Das Ergebnis sollte ähnlich dem Ergebnis aus Teilen nach Anzahl der Zeilen sein .

Dateien verbinden

Sie können Dateien auf zwei Arten verbinden. Der erste ist:

cat SmallFile.* > OutputBigVideoFile.avi

oder mit:

cat SmallFile.?? > OutputBigVideoFile.avi

Hinweis: Wenn Sie Dateien zusammenfügen, sollten kleine Dateien nicht beschädigt werden. Auch sollten sich alle kleinen (Teil-) Dateien im selben Verzeichnis befinden.

Nole
quelle