¿Es compatible la ordenación de ordenar un archivo en el lugar, como `sed - in-place`?

80

¿Estoy ciego o no hay ninguna opción al igual que --in-placepara sort?

Para guardar los resultados en el archivo de entrada, sed usa -i( --in-place).

Redirigir la salida de sortal archivo de entrada

sort < f > f

resulta en hacerlo vacío. Si no hay --in-placeopción, ¿tal vez hay algún truco para hacerlo de manera práctica ?

(Lo único que me viene a la mente:

sort < f > /tmp/f$$ ; cat /tmp/f$$ > f ; rm /tmp/f$$

Mudarse no es la elección correcta, ya que los permisos de los archivos pueden cambiar. Es por eso que sobrescribo con el contenido del archivo temporal que luego elimino).

Grzegorz Wierzowiecki
fuente
También existe insitu, permitiendo que cualquier comando se use en el lugar.
sr_
@sr_, ese es un comando interesante, pero no funciona con ningún comando, solo los que no escriben más rápido de lo que leen (de lo contrario, bloquearán el archivo de entrada antes de que el comando lo lea). No hay garantía de que funcione sort.
cjm
@cjm, realmente no estoy seguro, pero no es esto supone para manejar ese caso?
sr_
@sr_, creo que tienes razón. Leí la descripción en lugar de mirar la fuente. Aunque para archivos realmente grandes, podría quedarse sin memoria para el búfer y bloquearse (no parece que compruebe un retorno NULL de malloc).
cjm
@cjm: Oh sí, de hecho.
sr_

Respuestas:

110

sorttiene la -o, --outputopción que toma un nombre de archivo como argumento. Si es el mismo que el archivo de entrada, escribe el resultado en un archivo temporal, luego sobrescribe el archivo de entrada original (exactamente lo mismo que lo que sed -ihace).

Desde la GNU sortpágina de información:

`-o OUTPUT-FILE'
`--output=OUTPUT-FILE'
      Write output to OUTPUT-FILE instead of standard output.  Normally,
      `sort' reads all input before opening OUTPUT-FILE, so you can
      safely sort a file in place by using commands like `sort -o F F'
      and `cat F | sort -o F'.  However, `sort' with `--merge' (`-m')
      can open the output file before reading all input, so a command
      like `cat F | sort -m -o F - G' is not safe as `sort' might start
      writing `F' before `cat' is done reading it.

      On newer systems, `-o' cannot appear after an input file if
      `POSIXLY_CORRECT' is set, e.g., `sort F -o F'.  Portable scripts
      should specify `-o OUTPUT-FILE' before any input files.

y de The Open Group Base Especificaciones Número 7 :

-o  output
    Specify the name of an output file to be used instead of the standard 
    output. This file can be the same as one of the input files.
enzotib
fuente
Exactamente! Funciona ! No puedo ver ninguna pista al respecto, man sort¿es una función no documentada? ¿Es estándar y portátil?
Grzegorz Wierzowiecki
@GrzegorzWierzowiecki: ver actualización.
enzotib
Buena respuesta :).
Grzegorz Wierzowiecki
1
En resumen: sort -o <filename> <filename>ordenará de forma segura un archivo en su lugar.
phyatt
11

Puede usar la spongefunción, que primero empapa stdiny luego la escribe en un archivo, como:

sort < f | sponge f

La desventaja spongees que almacenará la salida temporal en la memoria, lo que puede ser problemático para archivos grandes. De lo contrario, primero debe escribirlo en un archivo y luego sobrescribir el archivo original.

Sin embargo, como señalan otras respuestas, las modificaciones en el lugar en general no son una buena idea, ya que en medio de un proceso (por ejemplo, el spongeuno), la máquina puede fallar y luego puede perder tanto el archivo original como el nuevo. Es mejor que primero lo escriba en un archivo diferente y luego use una mvinstrucción atómica (mover).

Willem Van Onsem
fuente
7

Es peligroso sobrescribir el archivo de entrada con el archivo de salida, porque si el programa o el sistema se bloquea mientras se está escribiendo el archivo, ha perdido ambos.

Algunos programas (en su mayoría versiones de GNU) tienen una opción in situ (por ejemplo, -ien perl y GNU sed; -oen GNU sort). Funcionan colocando los datos en un archivo temporal y luego moviéndolos a su lugar. Para los programas que no tienen esa opción, de Colin Watson spongeutilidad (incluido en moreutils de Joey Hess ) hace el trabajo de manera segura para cualquier programa (ejemplos: ¿Puedo hacer cut? Cambiar un archivo en su lugar ; ¿Cómo puedo hacer iconv reemplazar el archivo de entrada con el convertida salida? ).

Solo en esos raros casos en los que no puede volver a crear el archivo original con los mismos permisos, recomiendo sobrescribir el archivo en su lugar. En este caso, será mejor que guarde la entrada original en alguna parte. Y luego simplemente puede procesar la copia de la entrada y enviarla al archivo original.

cp -p f ~/f.backup
sort <~/f.backup >|f
rm ~/f.backup # optional
Gilles
fuente
1
sort -ono es específico de GNU, y está especialmente diseñado para modificar el archivo en su lugar. sortno puede comenzar a escribir su salida antes de que haya leído completamente sus entradas (usa memoria o archivos temporales para almacenar datos), por lo que es bastante natural que pueda anular su entrada.
Stéphane Chazelas
Y en realidad, es un caso en el que GNU sortno es POSIX, ya sort -mo file1 file1 file2que no se garantiza que funcione, mientras que los tradicionales sortsaben cómo solucionarlo (ya en Unix V7 en los años 70).
Stéphane Chazelas
@JoelCross Odd, sort -ofunciona para mí con coreutils 8.25 y la propiedad está documentada en el manual (teniendo en cuenta que solo es el caso al ordenar, no al fusionar). Si puede reproducir esto, envíe un informe de error (indicando la línea de comando exacta, los archivos de entrada exactos, en qué sistema lo está ejecutando y cómo obtuvo el binario).
Gilles
4

Usa -oo prueba el vim-way:

$ ex -s +'%!sort' -cxa file.txt
kenorb
fuente