What you want is a program that understands these terminal control sequences, and is able to render the final view. Well, such a program is called a terminal emulator. Some of them are graphical – like the program you launch to use your shell, e.g., gnome-terminal or alacritty, others are primarily headless.
The older screen
or the more modern tmux
are the relevant ones here.
- write an "outer" script:
- create a named pipe
- Start your "inner" script (so the one that outputs stuff) in
tmux
, in the background
- in your outer script, read from the fifo (this blocks because nothing has been written),
- once that read finishes, instruct
tmux
to output a screenshot
- in your inner script, write something to the named pipe to signal you're at a state to be taken a screenshot of
Putting it together, something like
#!/usr/bin/zsh
# outer script
# SPDX-License-Identifier: WTFPL
Make a temporary directory
tmpdir="$(mktemp -d)"
Prepare the FIFO
fifo="${tmpdir}/fifo"
mkfifo "${fifo}"
Start the inner script in tmux
tmux new-session -d -s "${tmpdir}" -e "FIFO=${fifo}" ./inner-script.sh …
#^ ^ ^ ^------+-----^ ^------+--------^ ^ ^
#| | | | | | |
#------run tmux, the terminal emulator
| | | | | |
---in tmux, run the "new-session" command to, well, get a new session
| | | | |
---detach that session, i.e. don't connect it to the current terminal
| | | |
--specify the session name. Conveniently, we abuse the name
of our temporary directory, as it's inherently unique
| | |
-- for the started command, set the environment
variable FIFO to the name of our FIFO
| |
-- launch your script
…with its arguments--/
Wait for something to be written to our FIFO
cat "${fifo}" > /dev/null
instruct tmux to take a "pane shot"
tmux capture-pane -t "${tmpdir}" -p > "/path/to/capture"
^------+-----^ ^ ^---------+--------^
| | |
-------------------------------- target (session name as above)
| |
----------------------- print to stdout
|
----------- redirect stdout to file
Finally, clean up session and temporary directory
tmux kill-session -t "${tmpdir}"
rm -rf "${tmpdir}"
You only need to add the writing of something to the fifo to your inner-script.sh
, e.g., echo done > "${FIFO}"; sleep 100
.
If you already have a "recorded" output, your inner-script.sh
might simply be cat recording.txt; echo done > "${FIFO}"; sleep 100
col
does that for Backspace, Carriage Return and Reverse Linefeed. I guess this is for some ancient printer — maybe the KSR-37? – G-Man Says 'Reinstate Monica' Mar 16 '24 at 20:50