Naming file using content of terminal output

This thread here discussed how to output terminal content to a file. Particularly, with this:

command |& tee output.txt

Question: is it possible to utilize part of the output content to name the file. For eg., suppose the content is printed out line by line as following:

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

Is it possible to use the content of the last line to name the file, instead of out.txt on the command line? Some sort of variable, maybe? Here, the last line is presumed to be defined as one that appears just before the file is closed (and the command finishes running).


Solution 1:

However you solve this, you're going to have to buffer the command output until you can read the last line, in order to know where to write it.

The only sensible way I can think of doing this is to use a temporary file, then rename it:

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

You can change | to |& if you really want to capture both stdout and stderr - but be aware that this may result in naming the output file after an error message (although there's probably a way to avoid that using clever file descriptor fu).

It may be possible to implement an alternate solution using the sponge command (from package moreutils) but that likely uses the same technique under the hood. In fact, the man page says

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

Another option might be to use rev to reverse the lines so that you can read the last line first, and then rev again to restore the output order. However that involves buffering the whole output twice.