Tengo muchos archivos de texto en un directorio y quiero eliminar la última línea de cada archivo en el directorio.
¿Cómo puedo hacerlo?
text-processing
files
ThehelfarisedPheonix
fuente
fuente
Respuestas:
Si tiene acceso a
vim
, puede usar:fuente
Puedes usar este bonito oneliner si tienes GNU
sed
.Eliminará la última línea de cada archivo no oculto en el directorio actual. Cambiar
-i
por GNUsed
significa operar en su lugar y'$ d'
ordenased
que elimine la última línea (lo que$
significa último y lo qued
significa eliminar).fuente
-i
que es un GNUism, así que esto es discutible, pero perdería mi antigua posición de barba si no señalara que algunas versiones anteriores desed
no te permiten poner ningún espacio en blanco entre el$
y eld
(o, en general, entre el patrón y el comando).*(.)
a glob para los archivos normales, no sé acerca de otras conchas.Todas las otras respuestas tienen problemas si el directorio contiene algo diferente a un archivo normal, o un archivo con espacios / líneas nuevas en el nombre del archivo. Aquí hay algo que funciona independientemente:
find "$dir" -type f
: Encontrar los archivos en el directorio$dir
-type f
que son archivos regulares;-exec
ejecutar el comando en cada archivo encontradosed -i
: Editar los archivos en su lugar;'$d'
: Eliminar (d
) la última ($
la línea).'+'
: le dice a find que continúe agregando argumentos ased
(un poco más eficiente que ejecutar el comando para cada archivo por separado, gracias a @zwol).Si no desea descender en subdirectorios, a continuación, puede agregar el argumento
-maxdepth 1
afind
.fuente
find
esto está escrito de manera más eficientefind $dir -type f -exec sed -i '$d' '{}' '+'
.)-print0
no está presente en el comando completo, ¿por qué ponerlo en la explicación?-depth 0
no funciona (findutils 4.4.2), debería funcionar-maxdepth 1
.-exec
.Usar GNU
sed -i '$d'
significa leer el archivo completo y hacer una copia sin la última línea, mientras que sería mucho más eficiente simplemente truncar el archivo en su lugar (al menos para archivos grandes).Con GNU
truncate
, puedes hacer:Si los archivos son relativamente pequeños, eso probablemente sería menos eficiente, ya que ejecuta varios comandos por archivo.
Tenga en cuenta que para los archivos que contienen bytes adicionales después del último carácter de nueva línea (después de la última línea) o, en otras palabras, si tienen una última línea no delimitada , entonces, dependiendo de la
tail
implementación,tail -n 1
devolverán solo esos bytes adicionales (como GNUtail
), o la última línea (delimitada correctamente) y esos bytes adicionales.fuente
|wc -c
en latail
llamada? (o a${#length}
)${#length}
no funcionaría ya que cuenta caracteres, no bytes, y$(...)
eliminaría el carácter de nueva línea de cola, por${#...}
lo que estaría desactivado por uno, incluso si todos los caracteres fueran de un solo byte.Un enfoque más portátil:
No creo que esto necesite ninguna explicación ... excepto tal vez que en este caso
d
es lo mismo$d
ya queed
por defecto selecciona la última línea.Esto no buscará recursivamente y no procesará archivos ocultos (también conocidos como archivos de puntos).
Si desea editarlos también, vea Cómo hacer coincidir * con archivos ocultos dentro de un directorio
fuente
[[]]
a[]
, será totalmente compatible con POSIX. ([[ ... ]]
es un Bashismo.)[[
no es un bashism )One-liner compatible con POSIX para todos los archivos que comienzan recursivamente en el directorio actual, incluidos los archivos de puntos:
.txt
Solo para archivos, de forma no recursiva:Ver también:
fuente