Respuestas:
Intenta en su ed
lugar:
ed <<< $'1d\nwq' large_file
Si ese "grande" significa unos 10 millones de líneas o más, mejor uso tail
. No es capaz de editar en el lugar, pero su rendimiento hace que esa falta sea perdonable:
tail -n +2 large_file > large_file.new
Editar para mostrar algunas diferencias de tiempo:
( awk
código de Jaypal agregado para tener tiempos de ejecución en la misma máquina (CPU 2.2GHz)).
bash-4.2$ seq 1000000 > bigfile.txt # further file creations skipped
bash-4.2$ time sed -i 1d bigfile.txt
time 0m4.318s
bash-4.2$ time ed -s <<< $'1d\nwq' bigfile.txt
time 0m0.533s
bash-4.2$ time perl -pi -e 'undef$_ if$.==1' bigfile.txt
time 0m0.626s
bash-4.2$ time { tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt; }
time 0m0.034s
bash-4.2$ time { awk 'NR>1 {print}' bigfile.txt > newfile.txt && mv -f newfile.txt bigfile.txt; }
time 0m0.328s
awk
y obtuve el siguiente resultado:[jaypal:~/Temp] seq 1000000 > bigfile.txt [jaypal:~/Temp] time awk 'NR>1 {print}' bigfile.txt >newfile.txt real 0m0.649s user 0m0.601s sys 0m0.033s
awk
el rendimiento fuera más cercano al sed
de. (Nota para mí: nunca esperes, prueba en su lugar)
tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt;
estoy usando un solo archivo con un bloqueo para realizar un seguimiento de una lista de tareas única utilizada por múltiples procesos. Empecé con lo que el cartel inicial utilizado: sed -i 1d large_file
. Eso estaba causando que el archivo se bloqueara durante 1-2 segundos. El tail/mv
combo se completa casi instantáneamente. ¡Gracias!
No hay forma de eliminar eficientemente las cosas desde el inicio de un archivo. Eliminar datos desde el principio requiere reescribir todo el archivo.
Sin embargo, el truncamiento desde el final de un archivo puede ser muy rápido (el sistema operativo solo tiene que ajustar la información del tamaño del archivo, posiblemente limpiando los bloques ahora no utilizados). Esto generalmente no es posible cuando intenta eliminar del encabezado de un archivo.
Teóricamente podría ser "rápido" si eliminara un bloque / extensión completo exactamente, pero no hay llamadas del sistema para eso, por lo que tendría que confiar en la semántica específica del sistema de archivos (si existe). (Supongo que tener alguna forma de desplazamiento dentro del primer bloque / extensión para marcar el inicio real del archivo. Nunca he oído hablar de eso tampoco).
El método más eficiente, ¡no lo hagas! Si lo hace, en cualquier caso, necesita el doble del espacio 'grande' en el disco y desperdicia las E / S.
Si está atascado con un archivo grande que desea leer sin la primera línea, espere hasta que necesite leerlo para eliminar la primera línea. Si necesita enviar el archivo desde stdin a un programa, use tail para hacerlo:
tail -n +2 | your_program
Cuando necesite leer el archivo, puede aprovechar la oportunidad para eliminar la primera línea, pero solo si tiene el espacio necesario en el disco:
tail -n +2 | tee large_file2 | your_program
Si no puede leer desde stdin, use un fifo:
mkfifo large_file_wo_1st_line
tail -n +2 large_file > large_file_wo_1st_line&
your_program -i large_file_wo_1st_line
incluso mejor si está usando bash, aproveche la sustitución del proceso:
your_program -i <(tail -n +2 large_file)
Si necesita buscar en el archivo, no veo una mejor solución que no quedar atascado con el archivo en primer lugar. Si este archivo fue generado por stdout:
large_file_generator | tail -n +2 > large_file
De lo contrario, siempre existe la solución de sustitución de procesos o fifo:
mkfifo large_file_with_1st_file
large_file_generator -o large_file_with_1st_file&
tail -n +2 large_file_with_1st_file > large_file_wo_1st_file
large_file_generator -o >(tail -n 2+ > large_file_wo_1st_file)
Puede usar Vim en modo Ex:
ex -sc '1d|x' large_file
1
seleccione primera línea
d
borrar
x
guardar y cerrar
Esto es solo teorizar, pero ...
Un sistema de archivos personalizado (implementado usando FUSE o un mecanismo similar) podría exponer un directorio cuyo contenido es exactamente el mismo que un directorio ya existente en otro lugar, pero con archivos truncados como desee. El sistema de archivos traduciría todas las compensaciones de archivos. Entonces no tendría que hacer una reescritura de un archivo que lleva mucho tiempo.
Pero dado que esta idea no es muy trivial, a menos que tenga decenas de terabytes de dichos archivos, implementar dicho sistema de archivos sería demasiado costoso / lento para ser práctico.
tail
, preferiría contar el tiempo para hacer tanto eliminar la primera línea y reemplazarbigfile.txt
con elbigfile.new
.