Jak podzielić stdout, aby przejść do kilku plików wyjściowych?


12

Powiedzmy, że mam polecenie, commandktóre wypisuje na standardowe wyjście ogromną liczbę linii:

line1
line2
.....
lineN

Chcę zapisać dane wyjściowe na dysku, ale nie jako pojedynczy plik, ale jako sekwencję plików, z których każdy ma 1000 wierszy standardowego wyjścia:

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

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

etc

Próbowałem google znaleźć odpowiedź, ale za każdym razem google kieruje mnie do teepolecenia, co w tej sytuacji jest bezużyteczne. Prawdopodobnie wpisuję nieprawidłowe zapytania.

Odpowiedzi:


24

Po zakończeniu zapisywania pliku zawsze można splitgo podzielić na części lub wiele plików na podstawie liczby wierszy.

split -l 1000 output_file

lub jeszcze lepiej po prostu spróbuj

command | split -l 1000 -

Spowoduje to podzielenie strumienia wyjściowego na pliki z każdym 1000 linii (domyślnie jest to 1000 linii bez opcji -l).

Poniższe polecenie zapewni dodatkową elastyczność w zakresie umieszczania lub wymuszania prefiksu nazwy pliku, który zostanie wygenerowany, gdy dane wyjściowe zostaną wygenerowane i podzielone w celu zapisania w pliku.

command | split -l 1000 - small-


Byłem zdezorientowany, więc dla innych jego split [arguments...] [input e.g. "-" for stdin] [output_prefix], na przykład: tar -c somedir | split --byes 100MB --numeric-suffixes --suffix-length=3 - somedir.tar.part-wypuściłbym wiązkę 100 MB plików o nazwach somedir.tar.part-000001, 002 i tak dalej.
ThorSummoner,

3

Możesz użyć skryptu bash lines.bash

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

i użyj go jako:

cat long_file.txt | bash lines.bash

Jedyny problem, który zauważyłem, to *logowanie się long_file.txt(ktoś mógłby to naprawić).


2
Ustaw IFSpusty ciąg, aby uniknąć podziału słów read. Służy -rdo wyłączania ucieczki odwrotnego ukośnika read. Usuń, -eaby uniknąć ucieczki odwrotnego ukośnika echo. Użyj cudzysłowu, aby uniknąć podziału słów echo. Używać -vw bashod 4,0 do uniknięcia rozpoczęciem procesu cząstkowego. Użyj post-inkrementacji, ponieważ twój obecny kod umieści w pierwszym pliku tylko 999 linii. a=0; while IFS='' read -r line; do printf -v filename "%04d.txt" $((a++/1000)); echo "$line" >> "$filename"; done
manatwork

@manatwork Dziękujemy. Tylko mój printfnie ma -vprzełącznika. ( bash 4.2.10). Przynajmniej nie ma tego na stronieprintf
xralf,

1
man printfdokumenty / usr / bin / printf, które nigdy nie mogłyby w życiu ustawić zmiennej środowiskowej. Zobacz help printfdokumentację printfwbudowaną powłoki.
manatwork

@manatwork OK. Wydaje się, że w ++/części jest jeszcze błąd składniowy .
xralf,

1
Jeszcze jedno: nie ma potrzeby używania sigil w obliczeniach arytmetycznych, chyba że konieczne jest wyraźne rozszerzenie parametrów. W interpretacji arytmetycznej zmienne są i tak oceniane.
manatwork
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.