Me está costando mucho entender cómo se usan los descriptores de archivos en los scripts de shell.
Conozco los conceptos básicos como
exec 5 > /tmp/foo
Entonces, fd 5 se adjunta a foo para escribir.
exec 6 < /tmp/bar
… para leer.
exec 5>&-
… cerrar fd.
Ahora, ¿qué hace esto?
#!/bin/bash
exec 5 > /tmp/foo
exec 6 < /tmp/bar
cat <&6 | while read a
do
echo $a >&5
done
Según tengo entendido &5
cierra el fd, entonces, ¿cómo se sigue redirigiendo la salida con éxito después de cada llamada?
Esta es una copia de pasta de:Aquí
Afirma usar esto sobre un simple archivo echo $a > file
lo haría mucho más rápido, sin embargo, no entiendo. Apreciaría cualquier enlace a un tutorial decente. Parece que los poderes de Google me están fallando.
Respuesta aceptada:
Primero, tenga en cuenta que la sintaxis para cerrar es 5>&-
o 6<&-
, dependiendo de si el descriptor de archivo se lee para escribir o para leer. Parece que hay un error tipográfico o de formato en esa publicación de blog.
Aquí está el guión comentado.
exec 5>/tmp/foo # open /tmp/foo for writing, on fd 5
exec 6</tmp/bar # open /tmp/bar for reading, on fd 6
cat <&6 | # call cat, with its standard input connected to
# what is currently fd 6, i.e., /tmp/bar
while read a; do #
echo $a >&5 # write to fd 5, i.e., /tmp/foo
done #
No hay cierre aquí. Debido a que todas las entradas y salidas van al mismo lugar en este ejemplo simple, no es necesario el uso de descriptores de archivos adicionales. Podrías escribir
cat </tmp/bar |
while read a; do
echo $a
done >/tmp/foo
El uso de descriptores de archivo explícitos se vuelve útil cuando desea escribir en varios archivos a la vez. Por ejemplo, considere una secuencia de comandos que envía datos a un archivo de salida de datos y registra datos en un archivo de registro y posiblemente también mensajes de error. Eso significa tres canales de salida:uno para datos, uno para registros y otro para errores. Dado que solo hay dos descriptores estándar para la salida, se necesita un tercero. Puede llamar a exec
para abrir los archivos de salida:
exec >data-file
exec 3>log-file
echo "first line of data"
echo "this is a log line" >&3
…
if something_bad_happens; then echo error message >&2; fi
exec >&- # close the data output file
echo "output file closed" >&3
El comentario sobre la eficiencia aparece cuando tiene una redirección en un bucle, como este (suponga que el archivo está vacío para empezar):
while …; do echo $a >>/tmp/bar; done
En cada iteración, el programa abre /tmp/bar
, busca el final del archivo, agrega algunos datos y cierra el archivo. Es más eficiente abrir el archivo de una vez por todas:
while …; do echo $a; done >/tmp/bar
Cuando hay varias redirecciones en diferentes momentos, llamar a exec
para realizar redirecciones en lugar de envolver un bloque en una redirección se vuelve útil.
exec >/tmp/bar
while …; do echo $a; done
Encontrará varios otros ejemplos de redirección navegando por io-redirection
etiqueta en este sitio.