redirection pipes exercises and linux shell unix redirect pipe

pipes - pipe linux command



¿Por qué no funciona "ordenar archivo1> archivo1"? (7)

Cuando estoy tratando de ordenar un archivo y guardar la salida ordenada en sí misma, como esta

sort file1 > file1;

el contenido del archivo1 se está borrando por completo, mientras que cuando intento hacer lo mismo con el comando ''tee'' como este

sort file1 | tee file1;

funciona bien [ed: "funciona bien" solo para archivos pequeños con temporización afortunada, causará la pérdida de datos en archivos grandes o con una programación de procesos poco útil] , es decir, sobrescribe la salida ordenada del archivo1 en sí misma y también la muestra en la salida estándar .

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


Bash abre un nuevo archivo vacío cuando lee la canalización y luego llama para ordenar.

En el segundo caso, tee abre el archivo después de que la clasificación ya haya leído el contenido.


Como explicaron otras personas, el problema es que la redirección de E / S se realiza antes de que se ejecute el comando de sort , por lo que el archivo se trunca antes de que la sort tenga la oportunidad de leerlo. Si piensa por un momento, la razón es obvia: el shell se encarga de la redirección de E / S, y debe hacerlo antes de ejecutar el comando.

El comando de sort tiene ''siempre'' (desde al menos la versión 7 UNIX) admitió una opción -o para hacer que la salida a uno de los archivos de entrada sea segura:

sort -o file1 file1 file2 file3

El truco con tee depende del tiempo y la suerte (y probablemente de un pequeño archivo de datos). Si tuviera un megabyte o un archivo más grande, supongo que el comando tee debería eliminarlos, al menos en parte. Es decir, si el archivo es lo suficientemente grande, el comando tee abriría el archivo para su salida y lo truncaría antes de que la sort terminara de leerlo.


El primer comando no funciona ( sort file1 > file1 ), porque cuando se usa el operador de redirección ( > o >> ) el shell crea / trunca el archivo antes de que se invoque incluso el comando de sort , ya que tiene mayor prioridad.

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

Por lo tanto, al usar cualquier otro comando similar, debe evitar usar el operador de redirección al leer y escribir en el mismo archivo, pero debe usar editores relevantes en el lugar para eso (por ex , ex , ed , sed ), por ejemplo:

ex ''+%!sort'' -cwq file1

o utilizar otros utensilios como sponge .

Afortunadamente para sort existe el parámetro -o que escribe los resultados en el archivo (como lo sugiere @Jonathan ), por lo que la solución es sencilla: sort -o file1 file1 .


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


No es prudente depender de cualquiera de estos comandos para que funcionen como usted espera.

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

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

Esto evita el problema de leer el archivo después de que se haya modificado parcialmente, lo que puede desordenar los resultados. También hace posible tratar con gracia los errores; Si el archivo tiene N bytes de longitud y solo tiene N / 2 bytes de espacio disponible 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, luego leerlo 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 tienen opciones -i (tenga en cuenta que la sintaxis de la opción sed -i puede variar). Pero estas opciones funcionan al crear archivos temporales; solo se realizan internamente.


No funciona porque la redirección ''>'' implica un 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 la sort . Por lo tanto, el contenido del file1 se truncará antes de que la sort tenga la oportunidad de leerlo.


Puedes usar este método

sort file1 -o file1

Esto ordenará y almacenará de nuevo al archivo original. Además, puede usar este comando para eliminar la línea duplicada:

sort -u file1 -o file1