Como dividir o stdout para ir para vários arquivos de saída?

12

Digamos, eu tenho um comando commandque imprime um grande número de linhas no stdout:

line1
line2
.....
lineN

Quero salvar a saída em disco, mas não como um único arquivo, mas como uma sequência de arquivos, cada um com 1000 linhas de stdout:

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

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

etc

Tentei pesquisar no Google a resposta, mas sempre que o Google me aponta para o teecomando, o que é inútil nessa situação. Provavelmente, estou inserindo consultas erradas.

DNNX
fonte

Respostas:

24

Quando terminar de salvar o arquivo, você poderá sempre splito arquivo em partes de arquivo ou vários arquivos com base no número de linhas.

split -l 1000 output_file

ou melhor ainda, tente

command | split -l 1000 -

Isso dividirá o fluxo de saída em arquivos com cada 1000 linhas (o padrão é 1000 linhas sem a opção -l).

O comando abaixo fornecerá flexibilidade adicional para colocar ou aplicar um prefixo ao nome do arquivo que será gerado quando a saída for gerada e dividida para armazenar no arquivo.

command | split -l 1000 - small-

Nikhil Mulley
fonte
Fiquei confuso, então, para outros, é split [arguments...] [input e.g. "-" for stdin] [output_prefix], por exemplo: tar -c somedir | split --byes 100MB --numeric-suffixes --suffix-length=3 - somedir.tar.part-produziria um monte de arquivos de 100 MB chamado somedir.tar.part-000001, 002 e assim por diante.
ThorSummoner
3

Você pode usar um script bash lines.bash

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

e use-o como:

cat long_file.txt | bash lines.bash

O único problema que notei é com o *login long_file.txt(alguém pode corrigi-lo).

xralf
fonte
2
Defina a IFSstring vazia para evitar a divisão de palavras read. Use -rpara desativar a barra invertida read. Remova -epara evitar que a barra invertida escape echo. Use aspas para evitar a divisão de palavras echo. Use -vno bash4.0 para evitar iniciar um subprocesso. Use pós-incremento, pois seu código atual colocará no primeiro arquivo apenas 999 linhas. a=0; while IFS='' read -r line; do printf -v filename "%04d.txt" $((a++/1000)); echo "$line" >> "$filename"; done
manatwork
@manatwork Obrigado. Só o meu printfnão tem -vswitch. ( bash 4.2.10) Pelo menos não está na página de manual deprintf
xralf 6/12/11
1
man printfdocumentos / usr / bin / printf, que nunca poderiam na vida definir uma variável de ambiente. Veja help printfa documentação printfinterna do shell.
Manatwork
@manatwork OK. Parece haver um erro de sintaxe na ++/parte ainda.
xralf
1
Mais uma coisa: não há necessidade de usar sigil na avaliação aritmética, a menos que você precise explicitamente da expansão dos parâmetros. Na expansão aritmética, as variáveis ​​são avaliadas de qualquer maneira.
Manatwork