Eliminar la última línea de un archivo en Bash
Tengo un archivo, foo.txt
, que contiene las siguientes líneas:
a
b
c
Quiero un comando simple que resulte en que el contenido de foo.txt
sea:
a
b
11 answers
Utilizando GNU sed
:
sed -i '$ d' foo.txt
La opción -i
no existe en GNU sed
versiones anteriores a la 3.95, por lo que debe usarla como filtro con un archivo temporal:
cp foo.txt foo.txt.tmp
sed '$ d' foo.txt.tmp > foo.txt
rm -f foo.txt.tmp
Por supuesto, en ese caso también podría usar head -n -1
en lugar de sed
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-23 21:43:29
Esta es, con mucho, la solución más rápida y sencilla, especialmente en archivos grandes:
head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt
Si desea eliminar la línea superior use esto:
tail -n +2 foo.txt
Que significa líneas de salida que comienzan en la línea 2.
No use sed
para eliminar líneas de la parte superior o inferior de un archivo it es muy, muy lento si el archivo es grande.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-22 15:17:29
Tuve problemas con todas las respuestas aquí porque estaba trabajando con un archivo ENORME (~300 Gb) y ninguna de las soluciones escaladas. Esta es mi solución:
dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )
En palabras: Averigüe la longitud del archivo con la que desea terminar (longitud del archivo menos longitud de la longitud de su última línea, utilizando bc
) y, establezca esa posición para que sea el final del archivo (mediante dd
un byte de /dev/null
en él).
Esto es rápido porque tail
comienza a leer desde el final, y dd
sobrescribirá el archivo en lugar en lugar de copiar (y analizar) cada línea del archivo, que es lo que hacen las otras soluciones.
NOTA: Esto elimina la línea del archivo en su lugar! Hacer una copia de seguridad o prueba en un archivo ficticio antes de probarlo en su propio archivo!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-06 19:34:09
Para eliminar la última línea de un archivo sin leer todo el archivo o reescribir nada , puede usar
tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}
Para eliminar la última línea y también imprimirla en stdout ("pop" it), puede combinar ese comando con tee
:
tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})
Estos comandos pueden procesar eficientemente un archivo muy grande. Esto es similar e inspirado en la respuesta de Yossi, pero evita el uso de algunas funciones adicionales.
Si vas a usar estos repetidamente y quieres manejo de errores y algunas otras características, puede usar el comando poptail
aquí:
https://github.com/donm/evenmoreutils
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-27 13:53:49
Usuarios de Mac
Si solo desea eliminar la última línea de salida sin cambiar el archivo en sí, haga
sed -e '$ d' foo.txt
Si desea eliminar la última línea del archivo de entrada, haga
sed -i '' -e '$ d' foo.txt
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-05 06:26:05
Para Usuarios de Mac :
En Mac, head-n -1 no funcionará. Y, estaba tratando de encontrar una solución simple [sin preocuparme por el tiempo de procesamiento] para resolver este problema solo usando comandos "head" y/o "tail".
Probé la siguiente secuencia de comandos y me alegré de poder resolverlo usando el comando "tail" [con las opciones disponibles en Mac]. Por lo tanto, si está en Mac y desea usar solo "tail" para resolver este problema, puede usar este comando :
Cat file.txt | tail-r | tail-n +2 / tail-r
Explicación:
1 > tail-r: simplemente invierte el orden de las líneas en su entrada
2 > tail-n + 2: esto imprime todas las líneas a partir de la segunda línea en su entrada
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-16 03:37:51
echo -e '$d\nw\nq'| ed foo.txt
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-28 06:03:49
awk 'NR>1{print buf}{buf = $0}'
Esencialmente, este código dice lo siguiente:
Para cada línea después de la primera, imprima la línea tamponada
Para cada línea, restablezca el búfer
El búfer está desfasado por una línea, por lo tanto, termina imprimiendo líneas 1 a n-1
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-03 01:47:44
awk "NR != `wc -l < text.file`" text.file |> text.file
Este fragmento hace el truco.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-13 15:09:53
Ambas soluciones están aquí en otras formas. Encontré esto un poco más práctico, claro y útil:
Usando dd:
BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
dd if=${ORIGINALFILE} of=${ORIGINALFILE}.tmp status=none bs=1 count=$(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc )
/bin/mv -f ${ORIGINALFILE}.tmp ${ORIGINALFILE}
Usando truncate:
BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-16 16:27:06
Ruby(1.9+)
ruby -ne 'BEGIN{prv=""};print prv ; prv=$_;' file
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-03 02:43:24