Ich habe ± 10.000 Dateien ( res.1
- res.10000
), die alle aus einer Spalte und einer gleichen Anzahl von Zeilen bestehen. Was ich will, ist im Wesentlichen einfach; Füge alle Dateien spaltenweise in einer neuen Datei zusammen final.res
. Ich habe versucht mit:
paste res.*
Jedoch (obwohl dies für einen kleinen Teil der Ergebnisdateien zu funktionieren scheint, dies gibt die folgenden Fehler , wenn sie auf dem ganzen Satz durchgeführt: Too many open files
.
Es muss einen "einfachen" Weg geben, dies zu tun, aber ich bin leider ziemlich neu in Unix. Danke im Voraus!
PS: Um Ihnen eine Vorstellung davon zu geben, wie (eine meiner) Datendateien aussieht:
0.5
0.5
0.03825
0.5
10211.0457
10227.8469
-5102.5228
0.0742
3.0944
...
--serial
Option mit dempaste
Befehl zu verwenden?paste --serial
führt Dateien nicht spaltenweise zusammen ...paste -s
funktioniert zwar, fügt aber die separaten Ergebnisdateien zeilenweise statt spaltenweise ein. Dies kann ich jedoch lösen. Vielen Dank!Antworten:
Wenn Sie über Root-Berechtigungen auf diesem Computer verfügen, können Sie das Limit für die "maximale Anzahl offener Dateideskriptoren" vorübergehend erhöhen:
Und dann
Danach können Sie die ursprünglichen Werte wiederherstellen.
Eine zweite Lösung , wenn Sie das Limit nicht ändern können:
Es ruft
paste
jede Datei einmal auf und am Ende gibt es eine riesige Datei mit allen Spalten (es dauert seine Minute).Edit : Nutzloser Einsatz von Katze ... Nicht !
Wie in den Kommentaren erwähnt, ist die Verwendung von
cat
here (cat final.res | paste - $f >temp
) nicht nutzlos. Beim ersten Ausführen der Schleife ist die Dateifinal.res
noch nicht vorhanden.paste
würde dann fehlschlagen und die Datei wird nie gefüllt, noch erstellt. Mit meiner lösungcat
scheitert nur das erste mal mit stdinNo such file or directory
undpaste
liest nur eine leere datei aus, aber es geht weiter. Der Fehler kann ignoriert werden.quelle
ulimit -Sn
für die weiche Grenze undulimit -Hn
für die harte Grenze-bash: /usr/bin/paste: Argument list too long
. Ideen, wie man das löst? Tut mir leid, dass ich euch gestört habe.getconf ARG_MAX
. Sie können diesen Wert nur erhöhen, wenn Sie den Kernel neu kompilieren. Sie können meine zweite Lösung versuchen?cat
jedes Mal durch die Schleife zu gehen, können Sie zunächst eine leerefinal.res
Datei erstellen. Dies ist wahrscheinlich in jedem Fall eine gute Idee, falls dort bereits einefinal.res
Datei vorhanden ist.Wenn die Antwort von chaos nicht zutrifft (weil Sie nicht über die erforderlichen Berechtigungen verfügen), können Sie die
paste
Anrufe wie folgt stapeln:Diese listet die Dateien 1000 zu einer Zeit , in Dateien mit dem Namen
lists00
,lists01
usw., dann fügt die entsprechendenres.
Dateien in Dateien mit dem Namenmerge00
,merge01
usw., und geht schließlich alle die daraus resultierenden teilweise Dateien zusammengefügt.Wie von Chaos erwähnt , können Sie die Anzahl der gleichzeitig verwendeten Dateien erhöhen. Das Limit ist der angegebene Wert
ulimit -n
abzüglich der Anzahl der Dateien, die Sie bereits geöffnet habendas Limit minus zehn zu verwenden.
Wenn Ihre Version von
split
nicht unterstützt-d
, können Sie sie entfernen: Sie müssen lediglichsplit
numerische Suffixe verwenden. Standardmäßig werden die Suffixeaa
,ab
usw. statt01
,02
usw.Wenn es so viele fehlgeschlagene Dateien gibt
ls -1 res.*
("Argumentliste zu lang"), können Sie sie ersetzen,find
um diesen Fehler zu vermeiden:(Wie von don_crissti hervorgehoben ,
-1
sollte dies beils
der Ausgabe von Pipelines nicht erforderlich sein. Ich überlasse es jedoch Fällen, in denenls
ein Alias vorliegt-C
.)quelle
Versuchen Sie es auf diese Weise auszuführen:
Sie können den Stapel auch in Teile aufteilen und Folgendes ausprobieren:
und am Ende kombinieren Sie die endgültigen Dateien
quelle
Too many open files
final.x00
be-Pipes entweder als benannte FIFOs oder implizit durch Prozessersetzung zu erstellen (sofern Ihre Shell dies unterstützt - z. B. bash). Es macht keinen Spaß, mit der Hand zu schreiben, kann aber durchaus zu einem Makefile passen.Ich denke nicht, dass dies so kompliziert ist wie das alles - Sie haben bereits die harte Arbeit geleistet, indem Sie die Dateinamen bestellt haben. Nur nicht alle gleichzeitig öffnen, ist alles.
Ein anderer Weg:
... aber ich denke das macht sie rückwärts ... Das könnte besser funktionieren:
Und hier ist noch ein anderer Weg:
Auf diese Weise können Sie
tar
alle Dateien in einem durch Nullen getrennten Stream zusammenfassen, alle Header-Metadaten mit Ausnahme des Dateinamens analysieren und alle Zeilen in allen Dateien in Registerkarten umwandeln. Es ist jedoch darauf angewiesen, dass es sich bei den Eingaben um tatsächliche Textdateien handelt. Dies bedeutet, dass jede Zeile mit einem Zeilenumbruch endet und die Dateien keine Nullbytes enthalten. Oh - und es stützt sich auch auf den Dateinamen selbst Newline frei zu sein (obwohl das vielleicht robust mit GNU behandelt werdentar
‚s ---xform
Option) . Wenn diese Bedingungen erfüllt sind, sollte eine beliebige Anzahl von Dateien in kürzester Zeit bearbeitet werden - undtar
dies ist fast alles.Das Ergebnis ist eine Reihe von Zeilen, die wie folgt aussehen:
Und so weiter.
Ich habe es getestet, indem ich zuerst 5 Testdateien erstellt habe. Ich habe wirklich nicht das Gefühl , wie genning 10000 Dateien gerade jetzt, so dass ich nur ein wenig größer für jede ging - und auch dafür gesorgt , dass die Dateilängen von viel unterschieden. Dies ist beim Testen von
tar
Skripten wichtig, datar
Eingaben mit festen Längen blockiert werden. Wenn Sie nicht mindestens ein paar verschiedene Längen ausprobieren, wissen Sie nie, ob Sie tatsächlich nur die eine verarbeiten.Wie auch immer, für die Testdateien, die ich gemacht habe:
ls
danach berichtet:... dann rannte ich ...
... um nur die ersten 25 durch Tabulatoren getrennten Felder pro Zeile anzuzeigen (da jede Datei eine einzelne Zeile ist - es gibt viele ) ...
Die Ausgabe war:
quelle
In Anbetracht der Anzahl der betroffenen Dateien, Zeilengrößen usw. denke ich, dass die Standardgrößen der Werkzeuge (awk, sed, paste, * usw.) übertroffen werden.
Ich würde ein kleines Programm dafür erstellen, es hätte weder 10.000 Dateien geöffnet, noch eine Zeile von Hunderttausenden Länge (10.000 Dateien von 10 (maximale Zeilengröße im Beispiel)). Es werden nur ~ 10.000 ganze Zahlen benötigt, um die Anzahl der Bytes zu speichern, die aus jeder Datei gelesen wurden. Der Nachteil ist, dass es nur einen Dateideskriptor gibt, der für jede Datei und für jede Zeile wiederverwendet wird. Dies kann langsam sein.
Die Definitionen von
FILES
undROWS
sollten auf die tatsächlichen exakten Werte geändert werden. Die Ausgabe wird an die Standardausgabe gesendet.quelle