Remoção de cabeçalho in-loco eficiente para arquivos grandes usando sed?

21

Os comandos abaixo podem levar alguns minutos dependendo do tamanho do arquivo. Existe algum método mais eficiente?

sed -i 1d large_file 
    
por Cheng 29.11.2011 / 11:07

5 respostas

30

Experimente ed :

ed <<< $'1d\nwq' large_file

Se esse "grande" significa cerca de 10 milhões de linhas ou mais, use melhor tail . Não é possível para edição no local, mas seu desempenho faz com que não seja perdoável:

tail -n +2 large_file > large_file.new

Editar para mostrar algumas diferenças de tempo:

(o código awk do Jaypal foi adicionado para ter tempos de execução na mesma máquina (CPU 2.2GHz).)

bash-4.2$ seq 1000000 > bigfile.txt # further file creations skipped

bash-4.2$ time sed -i 1d bigfile.txt
time 0m4.318s

bash-4.2$ time ed -s <<< $'1d\nwq' bigfile.txt
time 0m0.533s

bash-4.2$ time perl -pi -e 'undef$_ if$.==1' bigfile.txt
time 0m0.626s

bash-4.2$ time { tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt; }
time 0m0.034s

bash-4.2$ time { awk 'NR>1 {print}' bigfile.txt > newfile.txt && mv -f newfile.txt bigfile.txt; }
time 0m0.328s
    
por 29.11.2011 / 11:16
6

Não há como remover com eficiência as coisas do início de um arquivo. Remover dados desde o início requer reescrever todo o arquivo.

Truncar a partir do final de um arquivo pode ser muito rápido (o SO só precisa ajustar as informações de tamanho de arquivo, possivelmente limpando blocos não utilizados). Isso geralmente não é possível quando você tenta remover da cabeça de um arquivo.

Poderia teoricamente ser "rápido" se você removesse um bloco inteiro / extensão exatamente, mas não há chamadas de sistema para isso, então você teria que confiar na semântica específica do sistema de arquivos (se tal existir). (Ou ter alguma forma de deslocamento dentro do primeiro bloco / extensão para marcar o início real do arquivo, eu acho. Nunca ouvi falar disso também.)

    
por 29.11.2011 / 11:35
2

O método mais eficiente, não faça isso! Se você, em qualquer caso, você precisa de duas vezes o espaço 'grande' no disco, e você desperdiça IOs.

Se você estiver preso a um arquivo grande que deseja ler sem a 1ª linha, aguarde até precisar lê-lo para remover a 1ª linha. Se você precisar enviar o arquivo de stdin para um programa, use tail para fazer isso:

tail -n +2 | your_program

Quando você precisar ler o arquivo, aproveite a oportunidade para remover a primeira linha, mas somente se tiver o espaço necessário no disco:

tail -n +2 | tee large_file2 | your_program

Se você não consegue ler stdin, use um fifo:

mkfifo large_file_wo_1st_line
tail -n +2 large_file > large_file_wo_1st_line&
your_program -i large_file_wo_1st_line

de melhor ainda se você estiver usando o bash, aproveite a substituição do processo:

your_program -i <(tail -n +2 large_file)

Se você precisar procurar no arquivo, não vejo uma solução melhor do que não ficar com o arquivo em primeiro lugar. Se este arquivo foi gerado por stdout:

large_file_generator | tail -n +2 > large_file

Senão, há sempre a solução de substituição do processo ou fifo:

mkfifo large_file_with_1st_file
large_file_generator -o large_file_with_1st_file&
tail -n +2 large_file_with_1st_file > large_file_wo_1st_file

large_file_generator -o >(tail -n 2+ > large_file_wo_1st_file)
    
por 18.12.2011 / 15:21
1

Você pode usar o Vim no modo Ex:

ex -sc '1d|x' large_file
  1. 1 selecione a primeira linha

  2. d delete

  3. x salvar e fechar

por 17.04.2016 / 04:40
0

Isso é apenas teorização, mas ...

Um sistema de arquivos personalizado (implementado usando o FUSE ou um mecanismo similar) poderia expor um diretório cujo conteúdo é exatamente igual a um diretório já existente em algum outro lugar, mas com arquivos truncados como você deseja. O sistema de arquivos traduziria todos os deslocamentos de arquivo. Então você não precisaria fazer uma reescrita demorada de um arquivo.

Mas, dado que essa idéia é muito não-trivial, a menos que você tenha dezenas de terabytes de tais arquivos, implementar esse sistema de arquivos seria muito caro / demorado para ser prático.

    
por 29.11.2011 / 17:14