Você pode limpar arquivos temporários antes de serem usados ​​no shell?

Você pode limpar arquivos temporários antes de serem usados ​​no shell?

Quero evitar arquivos temporários se meu programa travar.

O UNIX é maravilhoso porque você pode manter um arquivo aberto - mesmo depois de excluí-lo.

Portanto, se você abrir o arquivo, exclua-o imediatamente eentãoSe você fizer o processamento lento, há grandes chances de que, mesmo que o programa trave, o usuário não precise limpar o arquivo.

No shell, muitas vezes vejo algo semelhante 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

Mas se o programa travar antes rmo usuário terá que limpar o arquivo the-file.

Em Perl você pode fazer:

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

Em seguida, o arquivo é removido assim que é aberto.

Existe uma construção semelhante no shell?

Responder1

Isso é testado em csh, tcsh, sh, ksh, zsh, bash, ash, sash:

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

ou se preferir:

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

Curiosamente, também funciona para fifos:

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

Isso ocorre porque o leitor fica bloqueado até que algo seja escrito.

Responder2

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

Notas:

  • Você precisa executar exec sem executável, então isso afeta os descritores do próprio shell
  • Somente até fd 9 disponível
  • Você pode usar /proc/self/fd/X se precisar de um nome de arquivo. Essa interface não é portátil entre versões UNIX (embora provavelmente funcione para você).
  • Tentar ler novamente o fd (por exemplo, duas chamadas para cat 0<&5) falhará porque você está no EOF. Você precisaria retroceder ou superá-lo lendo via/proc/self/fd/X
  • Na maioria dos casos, como acima, você poderia ficar sem um arquivo real e fazer um simplesgenerate-the-file | do_slow_processing

Atualizar:

O OP menciona que generate-the-filepode não produzir sua saída em stdout. Existem algumas expressões idiomáticas para isso:

  • Especifique um arquivo de saída de -. É comum aceitar um nome de arquivo de saída - para significar stdout. Isso éreconhecido por POSIX.1-2017:

    Diretriz 13: Para utilitários que usam operandos para representar arquivos a serem abertos para leitura ou gravação, o operando '-' deve ser usado para significar apenas entrada padrão (ou saída padrão quando estiver claro no contexto que um arquivo de saída está sendo especificado) ou um arquivo chamado -.

(para utilitários diferentes daqueles onde eles definem isso explicitamente, é definido pela implementação, mas há uma boa chance de que seja suportado pela sua generate-the-fileferramenta)

Isso não funcionará em todos os shells e requer suporte do sistema operacional para nomes de arquivos fd.

Responder3

No bashshell, a maneira de lidar com a limpeza é usando o EXIT trapembutido (de dentro de um bashshell, digite help trap):

trap 'rm temp-file' EXIT

Esse recurso também existe no dashshell, frequentemente apelidado de shdistribuições Linux modernas.

informação relacionada