2011-10-28 14 views
16

Cuando estoy tratando de ordenar un archivo y guardar la salida ordenada en sí mismo, como este¿Por qué no funciona el archivo "sort1> file1"?

sort file1 > file1; 

el contenido del archivo1 está llegando el borrado por completo, mientras que cuando estoy tratando de hacer lo mismo con 'T' comando como este

sort file1 | tee file1; 

funciona bien [ed: "funciona bien" sólo para un pequeño archivo con la sincronización suerte, provocará pérdida de datos en los grandes o con la planificación de procesos inútiles], es decir, que es sobrescribir la ordenada salida de file1 en sí mismo y también lo muestra en outp estándar Utah.

¿Alguien puede explicar por qué el primer caso no funciona?

+0

Dup de (http://superuser.com/q/142504/7542) – outis

Respuesta

13

No funciona porque la '>' redirección implica el truncamiento, y para evitar mantener toda la salida de sort en la memoria antes de redirigir al archivo, bash trunca y redirige la salida antes de ejecutar sort. Por lo tanto, el contenido del archivo file1 se truncará antes de que sort tenga la oportunidad de leerlo.

+0

No es 'para evitar que toda la salida de ordenar en la memoria antes de redirigir al archivo', y no es peculiar de 'bash'. La precedencia definida de '>' significa que se evalúa antes de ejecutar el programa, tan simple como eso, en todas las shells. – EJP

1

Bash abre un nuevo archivo vacío cuando lee el conducto, y luego llama para ordenar.

En el segundo caso, tee abre el archivo después de ordenar ya ha leído los contenidos.

+0

'tee' abre su archivo en un tiempo indeterminado relativo a cuando 'sort' abre su archivo. A veces tienes suerte, otras veces no. No es necesario que 'sort' haya leído todos los contenidos, solo que ha abierto el archivo primero. – EJP

1

La redirección tiene mayor prioridad. Entonces, en el primer caso,> file1 se ejecuta primero y vacía el archivo.

4

No es prudente depender de cualquiera de estos comandos para funcionar de la manera esperada.

La forma de modificar un archivo en su lugar es escribir la versión modificada en un nuevo archivo, cambie el nombre del archivo nuevo al nombre original:

sort file1 > file1.tmp && mv file1.tmp file1 

Esto evita el problema de la lectura del archivo después de que sea se ha modificado parcialmente, lo que puede estropear los resultados. También hace posible tratar con gracia los errores; si el archivo tiene una longitud de N bytes y solo tiene N/2 bytes de espacio disponibles en el sistema de archivos, puede detectar el error al crear el archivo temporal y no cambiar el nombre.

O puede cambiar el nombre del archivo original, a continuación, leer y escribir en un nuevo archivo con el mismo nombre:

mv file1 file1.bak && sort file1.bak > file1 

Algunos comandos tienen opciones para modificar archivos en su lugar (por ejemplo, perl y sed tanto tener -i opciones (tenga en cuenta que la sintaxis de la opción de sed -i puede variar) Sin embargo, estas opciones funcionan mediante la creación de archivos temporales;.. que acaba de hacer internamente

+3

Bueno, pero 'ordenar -o archivo1 archivo1' es mucho más simple y seguro. –

16

Como se ha explicado otras personas, el problema es que el cambio de dirección de E/S se realiza antes del sort c ommand se ejecuta, por lo que el archivo se trunca antes de que sort tenga la oportunidad de leerlo. Si piensa por un momento, la razón es obvia: el shell maneja la redirección de E/S y debe hacerlo antes de ejecutar el comando.

El comando sort tiene 'siempre' (por lo menos desde la Versión 7 de UNIX) apoyó una opción -o para que sea seguro para dar salida a uno de los archivos de entrada:

sort -o file1 file1 file2 file3 

El truco con tee depende del momento y suerte (y probablemente un pequeño archivo de datos). Si tiene un archivo de megabyte o más grande, espero que sea destruido, al menos en parte, por el comando tee. Es decir, si el archivo es lo suficientemente grande, el comando tee abrirá el archivo para su salida y lo truncará antes de que sort termine de leerlo.

+2

+1. Siempre vale la pena leer las páginas del manual –

1

El primer comando no funciona (sort file1 > file1), porque cuando se utiliza el operador de redirección (> o >>) crea la cáscara/trunca el archivo antes de que el comando se sort siquiera invocado, ya que tiene mayor precedencia.

El segundo comando funciona (sort file1 | tee file1), porque sort lee primero las líneas del archivo y luego escribe los datos clasificados en la salida estándar.

Así que cuando se utiliza cualquier otro comando similar, se debe evitar el uso de operador de redirección al leer y escribir en el mismo archivo, pero se debe utilizar editores relevantes en el lugar para que (por ejemplo ex, ed, sed), por ejemplo:

ex '+%!sort' -cwq file1 

o utilice otras utilidades como sponge.

suerte para sort no es el parámetro que -o escribir en el fichero de resultados (como se sugiere en @Jonathan), por lo que la solución es sencilla: sort -o file1 file1.

-2

Puede utilizar este método

sort file1 -o file1 

Esto ordenar y almacenar de nuevo al archivo original. Además, puede utilizar este comando para eliminar la duplicación de la línea: [? ORDENAR se vacía mi archivo]

sort -u file1 -o file1 
+0

ya mencionadas hace años. –

+0

Y no responde la pregunta real. – EJP

Cuestiones relacionadas