Divida um arquivo por linha e tenha controle sobre a extensão de arquivos resultante


28

Existe um comando padrão para divisão de arquivos - divisão.

Por exemplo, se eu quiser dividir um arquivo de palavras em vários pedaços de 10000 linhas, posso usar:

split -dl 10000 words wrd

e geraria vários arquivos no formato wrd.01, wrd.02 e assim por diante.

Mas quero ter uma extensão específica para esses arquivos - por exemplo, quero obter arquivos wtd.01.txt, wrd.02.txt.

Existe uma forma de fazer isso?

Respostas:


12

Não com split, mas você pode renomeá-los facilmente depois, ou pode fazê-lo em awk:

awk '{filename = "wrd." int((NR-1)/10000) ".txt"; print >> filename}' inputfile

Parece bom - mas não funciona. No seu formulário, reclama sobre "a expressão para o redirecionamento` >> 'tem valor nulo de string "e, se" file "for" alterado "para" filename ", gera arquivos com o formato wrd. {File number}. {Line number} .txt (bastante deles :)
Rogach

@ Rogach Desculpe, eu não tinha testado, então eu esqueci awk não faz divisão inteira. Eu testei este.
25412 Kevin

49

Isso não estava disponível na época, mas com as versões mais recentes ( ≥ 8.16) de gnu splituma pode-se usar a --additional-suffixopção para ter controle sobre a extensão resultante. De man split:

--additional-suffix=SUFFIX
              append an additional SUFFIX to file names.

portanto, ao usar essa opção:

split -dl 10000 --additional-suffix=.txt words wrd

as peças resultantes terminarão automaticamente em .txt:

wrd00.txt
wrd01.txt
.........

3
Não funciona no mac
ericgu

2
Eu amo o seu sarcasmo. Eu sou um n00b unix do mundo Apple. Estou usando o OS X Yosemite e não queria que outras pessoas travassem e queimassem como eu fiz. Testei e revi os documentos e não temos esse parâmetro. Eu poderia ter perdido alguma coisa. developer.apple.com/library/mac/documentation/Darwin/Reference/…
ericgu

5
@swiftshokunin - minha resposta pertence a gnu splitparte de gnu coreutils. Também está disponível no OSX se você instalar coreutilsvia, homebrewmas observe que, por padrão, no OSX, os gnuutilitários têm um gnome anexado ao seu nome (por exemplo, em gstatvez de stat), para que você o invoque como gsplit(ou altere o CAMINHO conforme o guia aqui, se desejar para usá-lo como splitno OSX split). HTH.
31515 don_crissti

11
Boa resposta. no OS X, use gsplitpara que os sufixos numéricos (-d) funcionem.
Brent Faust

11
uau, eu não tinha idéia de que existe o gsplit - provavelmente é do coreutils mencionado acima e possui - sufixo adicional. Obrigado a todos que comentam esta solução :)
Łukasz Rysiak

13

Essas tarefas são melhor gerenciadas com o shell. Use split e, em seguida, escreva um loop simples para renomear os arquivos. Por exemplo

for file in wrd.*
do
    mv "$file" "$file.txt"
done

renomearia seus arquivos wrd.01, wrd.02 etc. para que todos eles tivessem uma extensão .txt.


Isso é bastante óbvio, mas isso quebraria a concisão do script bash.
Rogach

11
A filosofia do Unix é fornecer a você um conjunto de ferramentas simples que você combina para realizar um trabalho. A "concisão do script bash" não era um requisito declarado na sua pergunta.
Kyle Jones

7
PS: o split+mvcombo é 6 vezes mais rápido que awk(aproximadamente 3s vs 18s ) para um arquivo de entrada de 10 milhões de linhas (75 MB) ... o texto em cada linha era seu próprio número de linha ... Obrigado por declarar o "óbvio" :)
Peter.O

3
PPS: Acabei de verificar isso um pouco mais. A diferença de velocidade está relacionada ao número de arquivos criados versus o número de cálculos aritméticos e de formatação que o awk faz para cada linha, independentemente do número de arquivos de saída ... Usando o mesmo arquivo de entrada que o exemplo acima: Quando houver 100 vezes menos arquivos, split + mvé 75 vezes mais rápido que awk: Quando há 100 vezes mais arquivos, split + mvé 1,5 vezes mais rápido que awk. Então, para mim, esse split + mvmétodo vence, sem dúvida. É como consice (indiscutivelmente mais), e é mais rápido que awk.
Peter.O

11
se você está preocupado com isso sendo 5 linhas, tente este em vez disso: for file in wrd.*; do mv "$file" "$file.txt"; done:)
Tony
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.