588

Short version: How can I make the less utility in Linux not wrap lines?

Long version: Often I need to view huge CSV files using less with hundreds of columns. I frequently only care about the first couple columns. However, word wrap causes one line to become several lines even on wide-screen monitors.

Franck Dernoncourt
  • 24,246
  • 64
  • 231
  • 400
User1
  • 9,701

5 Answers5

752

Note: For the key binding, see the second part.

In less, it's called line folding rather than line wrapping.  To set it not to fold, use the -S option:

-S, --chop-long-lines

Causes lines longer than the screen width to be chopped rather than folded. That is, the portion of a long line that does not fit in the screen width is not shown. The default is to fold long lines; that is, display the remainder on the next line.

less(1)


Alternatively, as mentioned in the below comment, if you already opened the file, you can toggle the mode by typing -S (and then Enter for some implementations).

After disabling line folding, you can scroll sideways with the arrow keys.

49

If you want to stop wrapping permanently, cast these spells:

echo "#env" >> ~/.lesskey
echo "LESS = -S" >> ~/.lesskey
lesskey
18

I use the most command which does that by default (and allows scrolling left/right to view it).

Franck Dernoncourt
  • 24,246
  • 64
  • 231
  • 400
jor
  • 706
10

To setup git so it never wraps:

git config --global core.pager 'less -S'
Franck Dernoncourt
  • 24,246
  • 64
  • 231
  • 400
0

The less -S recommendation is a complete nonstarter, because it causes less to send symbolic representations of control characters to the terminal rather than passing them raw.

Without the -S option, less can perfectly well unwrap lines, and send control characters to the terminal for syntax coloring and whatnot. The program demonstrates this ability whenever you use the arrow keys to scroll horizontally. As soon as you scroll away from column 1, the lines show without wrapping, yet with all the terminal effects intact.

All that users want is the same unwrapping to work in column 1 also.

Here is a hack script to clumsily bring it about:

#!/bin/sh

halfscreen=$((COLUMNS / 2)) spaces=$(printf "%*s" $halfscreen "")

sed -e "s/^/$spaces/' | less -# $halfscreen

We save this script under some name like lesshack.sh and make sure it is executable via chmod +x lesshack.sh. Then we use the script as the pager.

It relies on the COLUMNS variable, so we have to make sure this is exported into the environment via export COLUMNS.

How does this work? The script reads from standard input, and prepends half a screen width's worth of spaces to the beginning of each line.

When less comes up, we hit the right arrow key to scroll half a screen width to the right. That precisely skips the spaces we have added. So now we are looking at an unwrapped view of our data, without the -r option being disabled.

On Linux, we can inject the initial right arrow command into less via the TTY, using the TIOCSTI system call.

We switch the script to Bash, and add the ttyinject command, which we have to develop ourselves:

#!/bin/bash

halfscreen=$((COLUMNS / 2)) spaces=$(printf "%*s" $halfscreen "")

ttyinject $'\eOC' < /dev/tty sed -e "s/^/$spaces/" | less -# $halfscreen

The ttyinject utility inserts the specified characters into the TTY, as if they were input. It's a giant security hole that may have been disabled by default in Linux 6, but it's working for me on a system with a 5 kernel.

We are using $'\eOC. $'...' is Bash-specific syntax for a string literal in which C-like character escape sequences are interpreted. The \e escape is a GNU extension denoting ASCII ESC. ESC O C is the ANSI/VT100 right arrow sequence.

Here is the source code for ttyinject:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>

int main(int argc, char *argv) { if (argv[0] && argv[1]) { char inj = argv[1]; while (*inj) { if (ioctl(STDIN_FILENO, TIOCSTI, inj++) == -1) { perror("ioctl(TIOCSTI)"); return EXIT_FAILURE; } } }

return 0; }

One less refinement. With the above script, I see the injected characters being echoed to the terminal. They can be seen when less terminates and restores the screen. This is untidy. What we can do is run ttyinject in the background and with a small delay so that it takes effect after less has already started and switched the TTY to raw mode, disabling echo:

#!/bin/bash

halfscreen=$((COLUMNS / 2)) spaces=$(printf "%*s" $halfscreen "")

(sleep 0.1 ; ttyinject $'\eOC' < /dev/tty ) &

sed -e "s/^/$spaces/" | less -# $halfscreen

Kaz
  • 2,800
  • 1
  • 20
  • 24