Nomeando arquivo usando o conteúdo da saída do terminal

Nomeando arquivo usando o conteúdo da saída do terminal

Este tópicoaquidiscutimos como enviar o conteúdo do terminal para um arquivo. Particularmente, com isso:

command |& tee output.txt

Pergunta: é possível utilizar parte do conteúdo de saída para nomear o arquivo. Por exemplo, suponha que o conteúdo seja impresso linha por linha da seguinte forma:

action_1_last_time_2021_06_15_21_34_56
action_2_last_time_2021_06_15_21_35_23
action_3_last_time_2021_06_15_21_43_45
...
action_320032_last_time_2021_06_15_23_59_14

É possível usar o conteúdo da última linha para nomear o arquivo, em vez de out.txtna linha de comando? Algum tipo de variável, talvez? Aqui, presume-se que a última linha seja definida como aquela que aparece logo antes do arquivo ser fechado (e o comando terminar de ser executado).

Responder1

Independentemente de como você resolver isso, você terá que armazenar em buffer a saída do comando até poder ler a última linha, para saber onde escrevê-la.

A única maneira sensata de fazer isso é usar um arquivo temporário e renomeá-lo:

tmpfile=$(mktemp)
outfile=$(command | tee "$tmpfile" | tail -n 1)
mv "$tmpfile" "$outfile"

Você pode mudar |para |&se realmente deseja capturar stdout e stderr - mas esteja ciente de que issopoderiaresulta na nomeação do arquivo de saída após uma mensagem de erro (embora provavelmente haja uma maneira de evitar isso usando o descritor de arquivo inteligente fu).

Pode ser possível implementar uma solução alternativa usando o spongecomando (de package moreutils), mas isso provavelmente usa a mesma técnica nos bastidores. Na verdade, a página de manual diz

   When possible, sponge creates or updates the output file atomically by
   renaming a temp file into place.

Outra opção pode ser revinverter as linhas para que você possa ler a última linha primeiro e depois revnovamente para restaurar a ordem de saída. No entanto, isso envolve armazenar em buffer toda a saídaduas vezes.

informação relacionada