Como cortar um arquivo para um determinado tamanho no Linux?

19

Quero reduzir o tamanho de um arquivo com força bruta, ou seja, não me importo com o resto, só quero cortar o arquivo, digamos pela metade, e descartar o restante.

A primeira coisa que vem à mente é o truncado de Perl . Estou seguindo o exemplo nessa página e fiz exatamente a mesma coisa:

seq 9 > test.txt
ls -l test.txt
perl -we 'open( FILE, "< ./test.txt" ) && truncate( FILE, 8 ) && close(FILE);'

Mas o arquivo ainda tem o mesmo tamanho:

$ ls -lgG test.txt
-rw-rw---- 1 18 2013-08-08 09:49 test.txt

Como posso fazer isso funcionar?

xpt
fonte

Respostas:

62

Você pode querer usar o comando truncar :

truncate --size=1G test.txt

SIZE pode ser especificado como bytes, KB, K, MB, M, etc. Suponho que você possa calcular o tamanho desejado manualmente; caso contrário, você provavelmente poderia usar o comando stat para obter informações sobre o tamanho atual do arquivo.

ChrisInEdmonton
fonte
Sua documentação (em formato info) do coreutils.
Cristian Ciupitu
21
perl -we 'open( FILE, "< ./test.txt" ) && truncate( FILE, 8 ) && close(FILE);'

abre o arquivo para leitura. No entanto, para truncar o arquivo, você precisa modificá-lo, para que um identificador de arquivo somente leitura não funcione. Você precisa usar o modo "modificar" ( "+>").

Como uma questão secundária, sempre me surpreende quando as pessoas deixam as chamadas do sistema falharem silenciosamente e depois perguntam o que deu errado. Uma parte essencial do diagnóstico de um problema é observar a mensagem de erro produzida; mesmo que você não entenda, isso facilita muito a vida de quem pede ajuda.

O seguinte teria sido um pouco mais útil:

perl -we 'open(FILE, "<", "./test.txt") or die "open: $!";
          truncate(FILE, 8) or die "truncate: $!";
          close(FILE);'

embora seja certo que isso teria relatado apenas "argumento inválido". Ainda assim, essa é uma informação útil e pode ter levado você a concluir que o modo aberto estava errado (como aconteceu comigo).

rici
fonte
3

Você pode usar tailpara cortar os últimos 100000 bytes, exemplo:

tail -c 100000 arquivo> arquivo2

o -c gera os 100000 bytes finais do arquivo, para mais opções:

cauda de homem

Para substituir o arquivo original pelo arquivo que você acabou de gerar:

arquivo mv file2

Ivan Malyshev
fonte
2

A resposta acima citando truncado é boa. O dd também fará o trabalho:

dd if=test.txt of=test2.txt bs=1 count=8
mv test2.txt test.txt
James Georgas
fonte
11
A frase-chave é "para um determinado tamanho" , digamos 1000. Em vez disso, alterarei a resposta para a mais votada, que funciona de acordo com a entrada on-the-fly - não é necessário um arquivo intermediário.
xpt
0

existe uma maneira completamente diferente de fazer isso, com o bash, usando o programa ed. o script a seguir reterá apenas as últimas 5000 linhas de todos os arquivos localizados no diretório especificado. isso pode ser facilmente modificado para passar por vários diretórios, alterar o número de linhas etc.

#!/bin/bash

LOGDIR=/opt/log
SAVELINES=5000

dirs="$LOGDIR"
for dir in $dirs ; do
    files=${dir}/*
    for f in $files ; do
        echo -e "1,-${SAVELINES}d\nwq" | ed $f 1>/dev/null 2>&1
    done
done
Richard
fonte