23

Suppose I have some large datafile, which overflow the screen in both vertical and horizontal direction. How can I browse this file, while the header-lines stay on the screen?

For the moment, I am using less -S, so that I can nicely scroll my file horizontally and vertically. However, when scrolling down, the header lines obviously disappear. Is there a way to keep these using less?

An alternative is using vim in split-screen mode with :set nowrap. However, now if I scroll horizontally, the top window doesn't scroll in the same way (:windo set scrollbind only works for vertical scrolling as far as I know).

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
Bernhard
  • 11,992
  • 4
  • 59
  • 69
  • What do you mean by header stays visible, while the data keeps scrolling? Do you mean that you only want the first line with the column names keeps the same? Is it only one file with data and does this data keep changing and therefore you only want to see the changed rows? Do you only want to see the first N rows or last N rows? – polym Aug 06 '14 at 16:10
  • 4
    @polym: `less` or `tail -f` that behave exactly like they do normally, except that the first line shown on screen would always be the header line. Like websites (or Excel) with a fixed header but scrolling body. – Mat Aug 06 '14 at 16:12
  • @polym ^ whatever he said! – Debanjan Basu Aug 06 '14 at 16:36
  • 1
    @polym, Think of how you can freeze a horizontal and vertical view in a spreadsheet. Columns frozen stay in place while scrolling. – user208145 Mar 11 '18 at 15:58
  • Oh boy, that asks for an extension to less, like a Freeze Pane point. For example --freeze-pane 10,2 would keep 1 line of column headers and 10 columns row header. Horizontal and vertical scrolling would preserve the row and column headers respectively. That would be really cool to use for a psql pager (http://merlinmoncure.blogspot.com/2007/10/better-psql-with-less.html) – Gunther Schadow Jan 17 '20 at 19:19

7 Answers7

20

On terminals that support setting the scrolling region:

tailf() ( # args: <file> [<number-of-header-lines>]
  trap 'tput csr 0 "$((LINES-1))"' INT
  tput csr "$((1+${2-1}))" "$((LINES-1))"
  tput clear
  {
    head -n"${2-1}"
    printf "%${COLUMNS}s\n" "" | tr ' ' =
    tail -n "$((LINES-1-${2-1}))" -f
  } < "$1"
)

(assumes a shell like zsh or bash that sets the $COLUMNS and $LINES variables based on the size of the terminal).

Michael
  • 157
  • 9
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • 2
    Dude! That is godly! Sorry, couldn't control myself. Could you direct me to webpages or commands or variables to implement the following functions? – Debanjan Basu Aug 06 '14 at 16:42
  • 1. exit with `q` 2. scroll down with `up` and `down` keys – Debanjan Basu Aug 06 '14 at 16:43
  • is it possible to piggyback on `less` itself without using `head` and `tail` to redraw the screen each time? I still <3 your solution btw. I am not marking it correct yet because you seem to be editing it and I don't want you to get complacent; complacency is a creativity-killer, I am told! :) – Debanjan Basu Aug 06 '14 at 16:47
  • @DebanjanBasu you can use `less -X` in place of `tail -n ...` above but the "up" key deletes the header there. – Stéphane Chazelas Aug 06 '14 at 16:49
  • Like I said, if you have any better ideas just point me to that, or better still please tweak your answer further. I had to mark it correct because you **have** answered the question that I initially asked. The idea is to have a `less` environment sandwiched between a header and a footer, to make it a more general tool. – Debanjan Basu Aug 06 '14 at 17:03
  • @DebanjanBasu, you may want to wait a couple of days before accepting the answer to encourage people to post alternatives. – Stéphane Chazelas Aug 06 '14 at 17:14
13

If you're familiar with vim, this is probably the best option for you. You can enable horizontal-scroll-bind-only by changing 'scrollopt':

set scrollopt=hor

So with vim -u NONE, you get the desired behavior with:

:set scrollopt=hor
:set nowrap
:1split
:windo set scrollbind

You may want to adjust 'sidescroll' and 'sidescrolloff' to change how many columns are skipped and how far from the edge skipping starts respectively.

Thor
  • 16,942
  • 3
  • 52
  • 69
6

Try this (you'll need to install multitail):

multitail -du -t "$(head -n 1 filename)" filename

or, for headers longer than one line:

multitail -wh 2 -l "head -n 2 filename" filename

If you want to follow command output instead of a file:

multitail -wh 2 -l "command | head -n 2" -l command

or use -t as appropriate. Note that you may need to use unbuffer so your command output appears immediately.

You can use -D to disable the display of status lines for the -wh forms (it would defeat the purpose of the -t form).

Dennis Williamson
  • 6,620
  • 1
  • 34
  • 38
2

Thor's answer didn't mention disabling the vertical "scrollopt", which makes both windows scroll vertically. So for me the complete solution is pasting this into vim:

:set scrollopt+=hor
:set scrollopt-=ver
:set nowrap
:1split
:windo set scrollbind
tomasz
  • 123
  • 3
  • You can set `scrollopt` directly with `:scrollopt=hor` or `:scrollopt=hor,jump`, depending on your preferences. [Here's the VimDoc](http://vimdoc.sourceforge.net/htmldoc/options.html#'scrollopt') for `scrollopt`. – Michael Mar 04 '16 at 18:48
2

The bleeding edge version of less supports this with the --header option.

Less version 603 Release Notes

Version 603 was released for beta testing on 15 March 2022.

These are the differences between version 590 and version 603:

  • Add the --header option.
  • Add the --no-number-headers option.
  • Add the --status-line option.
  • ...

Source: https://greenwoodsoftware.com/less/news.603.html

muru
  • 69,900
  • 13
  • 192
  • 292
Kapocsi
  • 123
  • 5
1

This is as far as I got with tmux:

#!/bin/bash

tmux new-session -s main -n 'w1' -d
tmux send-keys -t main:w1.0 "tail -f <(head -n1 $1)" C-j
tmux split-window -v
tmux resize-pane -t 0 -y 2
tmux send-keys -t 1 "tail -n+2 $1|less -S" C-j
tmux attach -t main

It's an extension of user80519's answer for tmux window splitting. Save as hless.sh, make it executable and use it like

hless.sh file
Michael
  • 157
  • 9
Saddy
  • 11
  • 1
0

If it does not have to be a text-mode solution, you could use yad to display a list - actually a GTK+ dialog - with named columns. Maybe it has to read the whole file before you can browse, though.

jarno
  • 590
  • 4
  • 22