¿Puedes limpiar archivos temporales antes de usarlos en Shell?

¿Puedes limpiar archivos temporales antes de usarlos en Shell?

Quiero evitar tener archivos temporales por ahí si mi programa falla.

UNIX es maravilloso porque puedes mantener un archivo abierto, incluso después de eliminarlo.

Entonces, si abre el archivo, elimínelo inmediatamente yentoncesrealice el procesamiento lento, hay muchas posibilidades de que incluso si su programa falla, el usuario no tendrá que limpiar el archivo.

En Shell a menudo veo algo similar a:

generate-the-file -o the-file
[...loads of other stuff that may use stdout or not...]
do_slow_processing < the-file
rm the-file

Pero si el programa falla antes, rmel usuario tendrá que limpiarlo the-file.

En Perl puedes hacer:

open(my $filehandle, "<", "the-file") || die;
unlink("the-file");
while(<$filehandle>) {
  # Do slow processing stuff here
  print;
}
close $filehandle;

Luego, el archivo se elimina tan pronto como se abre.

¿Existe una construcción similar en Shell?

Respuesta1

Esto se prueba en csh, tcsh, sh, ksh, zsh, bash, ash, sash:

echo foo > the-file
(rm the-file; cat) < the-file | do_slow_processing
do_other_stuff

o si lo prefieres:

(rm the-file; do_slow_processing) < the-file
do_other_stuff

Curiosamente, también funciona para fifos:

mkfifo the-fifo
(rm the-fifo; cat) < the-fifo | do_slow_processing &
echo foo > the-fifo

Esto se debe a que el lector queda bloqueado hasta que se escribe algo.

Respuesta2

generate-the-file > the-file
exec 5< the-file
rm the-file
...
do_slow_processing 0<&5

Notas:

  • Necesita ejecutar exec sin ejecutable, por lo que afecta los descriptores del propio shell
  • Sólo hasta fd 9 disponible
  • Podrías usar /proc/self/fd/X si necesitas un nombre de archivo. Esta interfaz no es portátil entre versiones de UNIX (aunque probablemente funcione para usted).
  • Intentar leer nuevamente el fd (por ejemplo, dos llamadas a cat 0<&5) fallará ya que se encuentra en EOF. Debería rebobinarlo o superarlo leyendo a través de/proc/self/fd/X
  • En la mayoría de los casos, como se muestra arriba, puede prescindir de un archivo real y hacer una simplegenerate-the-file | do_slow_processing

Actualizar:

El OP menciona que generate-the-filees posible que no produzca su resultado en stdout. Hay algunos modismos para esto:

  • Especifique un archivo de salida de -. Es habitual aceptar un nombre de archivo de salida de - para significar salida estándar. Esto esreconocido por POSIX.1-2017:

    Directriz 13: Para las utilidades que usan operandos para representar archivos que se abrirán para lectura o escritura, el operando '-' debe usarse para indicar solo entrada estándar (o salida estándar cuando está claro por el contexto que se está especificando un archivo de salida) o un archivo llamado -.

(para utilidades distintas de aquellas en las que lo definen explícitamente, está definido por la implementación, pero es muy probable que sea compatible con su generate-the-fileherramienta)

Esto no funcionará en todos los shells y requiere soporte del sistema operativo para los nombres de archivos fd.

Respuesta3

En el bashshell, la forma de manejar la limpieza es mediante el uso del trapcomando EXIT (desde dentro del bashshell, escriba help trap):

trap 'rm temp-file' EXIT

Esta característica también existe en el dashshell, frecuentemente asociada a un alias shen las distribuciones modernas de Linux.

información relacionada