A abordagem sed
é boa, mas não é possível fazer o loop em todas as linhas. Se você souber quantas linhas deseja manter (para ter um exemplo, eu uso 99 aqui), você pode fazer assim:
sed -i '100,$ d' myfile.txt
Explicação: sed
é um processador de expressão regular. Com a opção -i
dada, ele processa um arquivo diretamente ("inline") - em vez de apenas lê-lo e gravar os resultados na saída padrão. 100,$
significa apenas "da linha 100 até o final do arquivo" - e é seguido pelo comando d
, que você provavelmente adivinhou corretamente para "excluir". Então, em suma, o comando significa: "Excluir todas as linhas da linha 100 para o final do arquivo de myfile.txt". 100 é a primeira linha a ser excluída, pois você deseja manter 99 linhas.
Editar: Se, por outro lado, houver arquivos de log em que você deseja manter, as últimas 100 linhas:
[ $(wc -l myfile.txt) -gt 100 ] && sed -i "1,$(($(wc -l myfile.txt|awk '{print $1}') - 100)) d" myfile.txt
O que está acontecendo aqui:
-
[ $(wc -l myfile.txt) -gt 100 ]
: faça o seguinte apenas se o arquivo tiver mais de 100 linhas
-
$((100 - $(wc -l myfile.txt|awk '{print $1}')))
: calcula o número de linhas a serem excluídas (isto é, todas as linhas do arquivo, exceto as (últimas) 100 a serem mantidas)
-
1, $((..)) d
: remova todas as linhas da primeira para a linha calculada
EDITAR: como a questão foi editada para dar mais detalhes, incluirei esta informação adicional com a minha resposta também. Fatos adicionados são:
- um tamanho específico permanecerá com o arquivo (10.000 bytes)
- cada linha tem um tamanho específico em bytes (300 bytes no exemplo)
A partir destes dados, é possível calcular o número de linhas a permanecer como "/", que com o exemplo significaria 33 linhas. O termo de shell para o cálculo: $((size_to_remain / linesize))
(pelo menos no Linux usando Bash, o resultado é um inteiro). O comando ajustado agora seria:
# keep the start of the file (OPs question)
sed -i '34,$ d' myfile.txt
# keep the end of the file (my second example)
[ $(wc -l myfile.txt) -gt 33 ] && sed -i "1,33 d" myfile.txt
Como os tamanhos são conhecidos antecipadamente, não há mais necessidade de um cálculo incorporado ao comando sed
. Mas, para flexibilidade, dentro de algum script de shell, é possível usar variáveis.
Para processamento condicional com base no tamanho do arquivo, pode-se usar a seguinte estrutura "teste":
[ "$(ls -lk $file | awk ' {print $5}')" -gt 100 ] &&
que significa: "se o tamanho de $file
exceder 100kB, faça ..." ( ls -lk
lista o tamanho do arquivo em kB na posição 5, portanto awk
é usado para extrair exatamente isso).