Wie kann man stdout aufteilen, um auf mehrere Ausgabedateien zuzugreifen?

12

Angenommen, ich habe einen Befehl, commandder eine große Anzahl von Zeilen an stdout ausgibt:

line1
line2
.....
lineN

Ich möchte die Ausgabe auf der Festplatte speichern, aber nicht als einzelne Datei, sondern als eine Folge von Dateien mit jeweils 1000 Zeilen stdout:

file0001.txt:
-------------
line1
....
line1000

file0002.txt:
-------------
line1001
....
line2000

etc

Ich habe versucht, die Antwort zu googeln, aber jedes Mal, wenn Google mich auf teeBefehl verweist , ist dies in dieser Situation nutzlos. Wahrscheinlich gebe ich falsche Abfragen ein.

DNNX
quelle

Antworten:

24

Sobald Sie mit dem Speichern der Datei fertig sind, können Sie splitdie Datei basierend auf der Anzahl der Zeilen immer in Dateiteile oder mehrere Dateien aufteilen.

split -l 1000 output_file

oder noch besser einfach mal probieren

command | split -l 1000 -

Dadurch wird der Ausgabestream in Dateien mit jeweils 1000 Zeilen aufgeteilt (Standard sind 1000 Zeilen ohne Option -l).

Mit dem folgenden Befehl können Sie dem Dateinamen, der beim Generieren und Aufteilen der Ausgabe zum Speichern in der Datei generiert wird, ein Präfix hinzufügen oder durchsetzen.

command | split -l 1000 - small-

Nikhil Mulley
quelle
Ich war verwirrt, und für andere ist es split [arguments...] [input e.g. "-" for stdin] [output_prefix]zum Beispiel so, tar -c somedir | split --byes 100MB --numeric-suffixes --suffix-length=3 - somedir.tar.part-dass ein Bündel von 100-MB-Dateien mit den Namen somedir.tar.part-000001, 002 und so weiter ausgegeben wird .
ThorSummoner
3

Sie können ein Bash-Skript verwenden lines.bash

#!/bin/bash
a=0
while IFS='' read -r line
do
  printf -v filename "%04d.txt" "$((a++/1000))"
  echo "$line" >> $filename
done

und benutze es als:

cat long_file.txt | bash lines.bash

Das einzige Problem, das mir aufgefallen ist, ist die *Anmeldung long_file.txt(jemand könnte es korrigieren).

xralf
quelle
2
Setzen Sie die Option IFSauf leere Zeichenfolge, um das Aufteilen von Wörtern zu vermeiden read. Verwenden Sie -rdiese Option, um das Entstehen von Backslash zu deaktivieren read. Entfernen -e, um ein Entweichen des Backslashs zu vermeiden echo. Verwenden Sie Anführungszeichen, um das Teilen von Wörtern zu vermeiden echo. Verwenden Sie -vin bashsince 4.0 zu vermeiden , dass ein Teilprozess zu starten. Verwenden Sie die Post-Inkrementierung, da Ihr aktueller Code in der ersten Datei nur 999 Zeilen enthält. a=0; while IFS='' read -r line; do printf -v filename "%04d.txt" $((a++/1000)); echo "$line" >> "$filename"; done
Handarbeit
@manatwork Danke. Nur mein Schalter printfhat nicht -v. ( bash 4.2.10). Zumindest ist es nicht in der Manpage vonprintf
xralf
1
man printfdocuments / usr / bin / printf, die niemals im Leben eine Umgebungsvariable setzen könnten. Weitere help printfInformationen zur integrierten printfShell finden Sie in der Dokumentation.
Handarbeit
@manatwork OK. Es scheint noch einen Syntaxfehler im ++/Teil zu geben.
Xralf
1
Eine weitere Sache: Es ist nicht erforderlich, Sigil in der arithmetischen Auswertung zu verwenden, es sei denn, Sie benötigen eine explizite Parametererweiterung. Bei der arithmetischen Erweiterung werden die Variablen trotzdem ausgewertet.
Manatwork