Eu tenho um grande número de arquivos, alguns dos quais são muito longos. Gostaria de truncá-los para um determinado tamanho, se eles forem maiores, removendo o final do arquivo. Mas eu só quero remover linhas inteiras. Como posso fazer isso? Parece o tipo de coisa que seria tratada pela cadeia de ferramentas Linux, mas não sei o comando certo.
Por exemplo, digamos que eu tenho um arquivo de 120.000 bytes com linhas de 300 bytes e estou tentando truncá-lo para 10.000 bytes. As primeiras 33 linhas devem permanecer (9900 bytes) e o restante deve ser cortado. Não quero cortar exatamente 10.000 bytes, pois isso deixaria uma linha parcial.
Obviamente, os arquivos têm diferentes comprimentos e as linhas não têm o mesmo comprimento.
Idealmente, os arquivos resultantes seriam reduzidos um pouco mais do que um pouco mais (se o ponto de interrupção estiver em uma longa linha), mas isso não for muito importante, poderá ser um pouco mais longo se for mais fácil. Gostaria que as alterações fossem feitas diretamente nos arquivos (bem, possivelmente o novo arquivo foi copiado em outro lugar, o original foi excluído e o novo arquivo foi movido, mas é o mesmo do POV do usuário). Uma solução que redireciona dados para vários lugares e depois convida a possibilidade de corromper o arquivo e eu gostaria de evitar isso ...
fonte
Respostas:
A complexidade
sed
/wc
pode ser evitada nas respostas anteriores seawk
for usada. Usando o exemplo fornecido do OP (mostrando linhas completas antes de 10000 bytes):Também mostrando a linha completa que contém 10000º byte, se esse byte não estiver no final da linha:
A resposta acima assume:
\n
). Para arquivos de texto do Dos / Windows (\r\n
), alterelength() + 1
paralength() + 2
LC_CTYPE=C
para forçar a interpretação no nível de bytes.fonte
A
sed
abordagem é boa, mas fazer um loop em todas as linhas não é. Se você souber quantas linhas deseja manter (para ter um exemplo, eu uso 99 aqui), é possível fazer o seguinte:Explicação:
sed
é um processador de expressão regular. Com a opção-i
fornecida, 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 comandod
, que você provavelmente adivinhou corretamente como "delete". Portanto, em resumo, o comando significa: "Exclua todas as linhas da linha 100 até o final do arquivo do 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 onde você deseja manter, por exemplo, as últimas 100 linhas:
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 (ou seja, todas as linhas do arquivo, exceto as (últimas) 100 a serem mantidas)1, $((..)) d
: remova todas as linhas da primeira para a linha calculadaEDIT: como a pergunta foi editada para fornecer mais detalhes, incluirei essas informações adicionais também com a minha resposta. Os fatos adicionados são:
A partir desses dados, é possível calcular o número de linhas para permanecer como "/", o que com o exemplo significaria 33 linhas. O termo do shell para o cálculo:
$((size_to_remain / linesize))
(pelo menos no Linux usando Bash, o resultado é um número inteiro). O comando ajustado agora seria:Como os tamanhos são conhecidos antecipadamente, não há mais necessidade de um cálculo incorporado ao
sed
comando. Mas, para flexibilidade, dentro de algum script shell, podemos usar variáveis.Para processamento condicional com base no tamanho do arquivo, pode-se usar a seguinte construção de "teste":
o que significa: "se o tamanho
$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).fonte
head -n
.Não encontrei um comando para fazer isso, escrevi um script rápido (não testado):
fonte
Você pode usar o comando linux sed para remover linhas de um arquivo. O comando a seguir exclui a última linha do nome do arquivo.txt:
Com awk ou find, você pode procurar por padrões que correspondam ao seu comando sed. Primeiro você pesquisa com o awk ou encontra os arquivos que deseja encurtar e depois pode remover as linhas com o sed.
fonte
Eu fiz algo semelhante com cauda. Para manter apenas as últimas 10.000 linhas neste caso:
fonte