Respostas:
Tente ed
:
ed <<< $'1d\nwq' large_file
Se esse "grande" significa cerca de 10 milhões de linhas ou mais, use melhor tail
. Não é capaz de editar no local, mas seu desempenho torna essa falta perdoável:
tail -n +2 large_file > large_file.new
Edite para mostrar algumas diferenças de horário:
( awk
código de Jaypal 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
awk
e obteve o seguinte resultado -[jaypal:~/Temp] seq 1000000 > bigfile.txt [jaypal:~/Temp] time awk 'NR>1 {print}' bigfile.txt >newfile.txt real 0m0.649s user 0m0.601s sys 0m0.033s
awk
o desempenho estivesse mais próximo sed
do. (Nota para mim mesma: nunca espera - de teste.)
tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt;
estou usando um único arquivo com um bloqueio para acompanhar uma única lista de tarefas usada por vários processos. Comecei com o que o cartaz inicial utilizado: sed -i 1d large_file
. Isso estava causando o bloqueio do arquivo por 1-2 segundos. A tail/mv
combinação é concluída quase instantaneamente. Obrigado!
Não há como remover coisas com eficiência desde o início de um arquivo. A remoção de dados desde o início requer a reescrita de todo o arquivo.
Truncar a partir do final de um arquivo pode ser muito rápido (o sistema operacional precisa apenas ajustar as informações de tamanho do arquivo, possivelmente limpando os blocos não utilizados). Isso geralmente não é possível quando você tenta remover da cabeça de um arquivo.
Teoricamente, poderia ser "rápido" se você removesse todo um bloco / 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 houver). (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.)
O método mais eficiente, não faça isso! Se você precisar, em qualquer caso, precisará do dobro do espaço "grande" no disco e desperdiçará IO.
Se você estiver preso com 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, poderá aproveitar a oportunidade para remover a 1ª linha, mas apenas se tiver o espaço necessário no disco:
tail -n +2 | tee large_file2 | your_program
Se você não consegue ler do 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
ainda melhor 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 preso ao arquivo em primeiro lugar. Se este arquivo foi gerado pelo stdout:
large_file_generator | tail -n +2 > large_file
Caso contrário, sempre há a solução de substituição de processo ou processo:
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)
Você pode usar o Vim no modo Ex:
ex -sc '1d|x' large_file
1
selecione a primeira linha
d
excluir
x
salvar e fechar
Isso é apenas teorização, mas ...
Um sistema de arquivos personalizado (implementado usando o FUSE ou um mecanismo similar) pode expor um diretório cujo conteúdo é exatamente o mesmo que um diretório já existente em outro lugar, mas com os arquivos truncados conforme desejado. O sistema de arquivos converteria todos os deslocamentos de arquivos. Então você não precisaria reescrever um arquivo demorado.
Mas, como essa idéia não é trivial, a menos que você tenha dezenas de terabytes desses arquivos, implementar esse sistema de arquivos seria muito caro / demorado para ser prático.
tail
, eu prefiro contar o tempo para fazer tanto remover a primeira linha e substituirbigfile.txt
combigfile.new
.