¿Cómo cortar un archivo a un tamaño determinado en Linux?

19

Quiero reducir el tamaño de un archivo por fuerza bruta, es decir, no me importa el resto, solo quiero cortar el archivo, digamos a la mitad, y descartar el resto.

La primera cosa que viene a la mente es de Perl truncado . Estoy siguiendo el ejemplo en esa página e hice exactamente lo mismo:

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

Pero el archivo todavía tiene el mismo tamaño:

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

¿Cómo puedo hacer que esto funcione?

xpt
fuente

Respuestas:

62

Es posible que desee utilizar el comando truncar :

truncate --size=1G test.txt

El TAMAÑO se puede especificar como bytes, KB, K, MB, M, etc. Supongo que puede calcular el tamaño deseado a mano; de lo contrario, probablemente podría usar el comando stat para obtener información sobre el tamaño actual del archivo.

ChrisInEdmonton
fuente
Su documentación (en formato de información) de coreutils.
Cristian Ciupitu
21
perl -we 'open( FILE, "< ./test.txt" ) && truncate( FILE, 8 ) && close(FILE);'

abre el archivo para leer. Sin embargo, para truncar el archivo, debe modificarlo, por lo que un identificador de archivo de solo lectura no funcionará. Necesita usar el modo "modificar" ( "+>").

Como cuestión secundaria, siempre me sorprende cuando las personas dejan que las llamadas del sistema fallen silenciosamente y luego preguntan qué salió mal. Una parte esencial del diagnóstico de un problema es mirar el mensaje de error producido; incluso si no lo entiendes, hace la vida mucho más fácil para quienes pides ayuda.

Lo siguiente habría sido algo más útil:

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

aunque es cierto que solo habría informado "argumento inválido". Aún así, esa es información útil y bien podría haberte llevado a la conclusión de que el modo abierto era incorrecto (como lo hizo para mí).

rici
fuente
3

Puede usar tailpara cortar los últimos 100000 bytes, por ejemplo:

cola -c 100000 archivo> archivo2

El -c genera los 100000 bytes finales del archivo, para más opciones:

cola de hombre

Para reemplazar el archivo original con el archivo que acaba de generar:

mv file2 file

Ivan Malyshev
fuente
2

La respuesta anterior citando truncado es agradable. dd también hará el trabajo:

dd if=test.txt of=test2.txt bs=1 count=8
mv test2.txt test.txt
James Georgas
fuente
1
La frase clave es "a un tamaño dado" , digamos 1000. En su lugar, cambiaré la respuesta a la más votada, que funciona a la entrada sobre la marcha, no necesita un archivo intermedio.
xpt
0

Hay una manera completamente diferente de hacer esto, con bash, usando el programa ed. el siguiente script retendrá solo las últimas 5000 líneas de todos los archivos que se encuentran en el directorio especificado. Esto se puede modificar fácilmente para recorrer varios directorios, cambiar el número de líneas, 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
Ricardo
fuente