I try to create a one-liner for opening less
on the last screen of an multi-screen output coming from standard input. The reason for this is that I am working on a program that produces a long AST
and I need to be able to traverse up and down through it but I would prefer to start at the bottom. I came up with this:
$ python a.py 2>&1 | tee >(lines=+$(( $(wc -l) - $LINES))) | less +$lines
First, I need to compute number of lines in output and subtract $LINES
from it so I know what's the uppermost line of the last screen. I will need to reuse a.py
output later so I use tee
with process substitution for that purpose. As the last step I point less
to open an original stdout on a particular line. Of course, it doesn't work in Bash
because $lines
is not set in last step as every subcommand is run in a subshell. In ZSH
, even though pipe commands are not run in a subshell, process substitution still is and therefore it doesn't work neither. It's not a homework or a work task, I just wonder whether it's possible to do what I want without creating a temporary file in Bash
or ZSH
. Any ideas?
The real answer to your question should be the option +G
to less
, but you indicated that the problem definition is not representative for the abstract problem you want to solve. Therefore, please consideer this alternative problem:
python a.py 2>&1 | \
awk '
{a[NR]=$0}
END{
print NR
for (i=1;i<=NR;i++)print a[i]
}
' | {
read -r l
less -j-1 +$l
}
The awk
command is printing the number of lines, and then all the lines in sequence. We define the first line to contain some meta information. This is piped to a group of commands delimited by {
and }
. The first line is consumed by read
, which stores it in variable $l
. The rest of the lines are taken by less
, where this variable can be used. -j-1
is used, so the matched line is at the bottom of the screen.