user1042840
user1042840

Reputation: 1955

bash one-liner for opening `less` on the last screen w/o temporary files

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?

Upvotes: 2

Views: 188

Answers (2)

joepd
joepd

Reputation: 4841

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.

Upvotes: 1

Michael Homer
Michael Homer

Reputation: 1117

less supports this innately. The + syntax you're using accepts any less command you could enter while it's running, including G for go-to-end.

... | less +G

does exactly what you want.

This is actually mentioned explicitly as an example in the man page (search for "+G").

Upvotes: 4

Related Questions