Tengo el escenario donde se agregarán líneas al comienzo y al final de los archivos enormes.
He intentado como se muestra a continuación.
para la primera línea:
sed -i '1i\'"$FirstLine" $Filename
para la última línea:
sed -i '$ a\'"$Lastline" $Filename
Pero el problema con este comando es que agrega la primera línea del archivo y atraviesa todo el archivo. Para la última línea, nuevamente atraviesa todo el archivo y agrega una última línea. Dado que es un archivo muy grande (14 GB), esto lleva mucho tiempo.
¿Cómo puedo agregar una línea al principio y otra al final de un archivo mientras solo leo el archivo una vez?
fuente
for
bucle:for file in Tes*; do [command]; done
"$file"
, noTes*
como argumento para hacerloed
.Tenga en cuenta que si desea evitar asignar una copia completa del archivo en el disco, puede hacer lo siguiente:
Eso utiliza el hecho de que cuando su stdin / stdout es un archivo,
sed
lee y escribe por bloque. Entonces, está bien que anule el archivo que está leyendo siempre que la primera línea que agregue sea más pequeña quesed
el tamaño de bloque (debería ser algo así como 4k u 8k).Sin embargo
sed
, tenga en cuenta que si por alguna razón falla (muerto, falla de la máquina ...), terminará con el archivo medio procesado, lo que significará que faltan algunos datos del tamaño de la primera línea en algún lugar en el medio.También tenga en cuenta que a menos que su
sed
sea GNUsed
, eso no funcionará para datos binarios (pero como está usando-i
, está usando GNU sed).fuente
Aquí hay algunas opciones (todas las cuales crearán una nueva copia del archivo, así que asegúrese de tener suficiente espacio para eso):
eco simple / gato
awk / gawk etc.
awk
y es como leer archivos línea por línea. ElBEGIN{}
bloque se ejecuta antes de la primera línea y elEND{}
bloque después de la última línea. Entonces, el comando anterior significaprint "first" at the beginning, then print every line in the file and print "last" at the end
.Perl
Esto es esencialmente lo mismo que el gawk anterior escrito en Perl.
fuente
sed -i
que crea archivos temporales.Prefiero el mucho más simple:
Esto transforma el archivo:
al archivo:
fuente
Puede usar Vim en modo Ex:
1
seleccione primera líneai
insertar texto y nueva línea$
seleccione la última líneaa
agregar texto y nueva líneax
guardar y cerrarfuente
No hay forma de insertar datos al comienzo de un archivo¹, todo lo que puede hacer es crear un nuevo archivo, escribir los datos adicionales y agregar los datos antiguos. Por lo tanto, tendrá que reescribir todo el archivo al menos una vez para insertar la primera línea. Sin embargo, puede agregar la última línea sin reescribir el archivo.
Alternativamente, puede combinar los dos comandos en una ejecución de sed.
sed -i
crea un nuevo archivo de salida y luego lo mueve sobre el archivo anterior. Esto significa que mientras sed funciona, hay una segunda copia del archivo que utiliza espacio. Puede evitar esto sobrescribiendo el archivo en su lugar , pero con restricciones importantes: la línea que está agregando debe ser más pequeña que el búfer de sed, y si su sistema falla, terminará con un archivo dañado y algo de contenido perdido en el medio, así que lo recomiendo encarecidamente.¹ Linux tiene una forma de insertar datos en un archivo, pero solo puede insertar un número entero de bloques del sistema de archivos, no puede insertar cadenas de longitudes arbitrarias. Es útil para algunas aplicaciones, como bases de datos y máquinas virtuales, pero es inútil para archivos de texto.
fuente
fallocate()
conFALLOC_FL_INSERT_RANGE
disponible en XFS y ext4 en kernels modernos (4.xx) man7.org/linux/man-pages/man2/fallocate.2.htmlfuente
Los núcleos modernos de Linux (superiores a 4.1 o 4.2) admiten la inserción de datos al comienzo de un archivo a través de la
fallocate()
llamada al sistema con losFALLOC_FL_INSERT_RANGE
sistemas de archivos ext4 y xfs. En esencia, esta es una operación de cambio lógico: los datos se reubican lógicamente en un desplazamiento más alto.Existe una restricción con respecto a la granularidad del rango que desea insertar al comienzo del archivo. Pero para los archivos de texto, probablemente pueda asignar un poco más de lo requerido (hasta el límite de granularidad) y llenar con espacios o retornos de carro, pero eso depende de su aplicación
No conozco ninguna utilidad de Linux fácilmente disponible que manipule las extensiones de archivo, pero no es difícil de escribir: obtenga un descriptor de archivo y llame
fallocate()
con los argumentos apropiados. Para obtener más detalles, consulte la página de manual de lafallocate
llamada del sistema: http://man7.org/linux/man-pages/man2/fallocate.2.htmlfuente
fallocate
utilidad. El problema es que una granularidad de bloques completos hace que esto sea inútil para la mayoría de los archivos de texto. Otro problema es que la asignación de rango y la modificación posterior no son atómicas. Entonces, esto en realidad no resuelve el problema aquí.fallocate
atomicidad está rota, por favor, tengo curiosidad)