less
Read a file a screen at a time, and search it
less shows a file a screen at a time and lets you move around inside it. It is Debian's default
pager, so man, systemctl and
journalctl all
hand their output to it. The shared inheritance is why they all quit on q, and why several of
them grew a --no-pager flag.
The keys are what no example can show. All of these are listed by
less --help, and h prints the same list without leaving the file.
| Key | What it does |
|---|---|
q |
quit |
SPACE, b |
forward, back one screen |
g, G |
first line, last line |
/text, ?text |
search forward, search backward |
n, N |
next match, previous match |
&text |
show only the lines that match |
F |
keep reading as the file grows, like tail -f; Ctrl-C stops |
v |
open the file in $VISUAL or $EDITOR |
-N then Enter |
turn line numbers on or off without restarting |
Searching is case-sensitive. -i makes it ignore case for any pattern with no capital letter in
it, and -I ignores case whatever the pattern looks like.
The behaviour that catches people out is on the other side. less pages only while it is talking
to a terminal. Send it into a pipe or a file and it copies its input straight through, ignoring
every display flag you gave it, so less -N report.txt > numbered.txt writes a file with no
numbers in it.
Sample files used on this page
Every example below was run against these files. Recreate them to follow along.
report.txt forty numbered lines, the same file the wc and head pages count
line 1 of the report
line 2 of the report
line 3 of the report
…
line 40 of the report
access.log ten requests in combined log format, as the second file for the examples that open two
203.0.113.5 - - [13/Aug/2026:09:12:01] "GET /index.html HTTP/1.1" 200 512
203.0.113.5 - - [13/Aug/2026:09:12:03] "GET /style.css HTTP/1.1" 200 231
198.51.100.7 - - [13/Aug/2026:09:14:22] "GET /index.html HTTP/1.1" 200 512
198.51.100.7 - - [13/Aug/2026:09:14:25] "GET /missing.html HTTP/1.1" 404 162
203.0.113.5 - - [13/Aug/2026:09:15:47] "GET /index.html HTTP/1.1" 200 512
192.0.2.44 - - [13/Aug/2026:09:16:03] "POST /login HTTP/1.1" 302 0
192.0.2.44 - - [13/Aug/2026:09:16:04] "GET /dashboard HTTP/1.1" 200 4021
198.51.100.7 - - [13/Aug/2026:09:18:51] "GET /index.html HTTP/1.1" 200 512
203.0.113.5 - - [13/Aug/2026:09:19:10] "GET /api/status HTTP/1.1" 500 89
192.0.2.44 - - [13/Aug/2026:09:20:33] "GET /dashboard HTTP/1.1" 200 4021
Opening a file
less report.txt and then q. Everything here needs a terminal to do anything at all, which is why none of it carries output: these flags change the screen less draws, and a replay has no screen.
Page through a file
less report.txt
Forty lines, one screen at a time, q to leave. Nothing is loaded up front. A log far larger than memory opens straight away, where cat would spend both the time and the memory.
Number the lines while reading
less -N report.txt
-N (--LINE-NUMBERS) puts a line number in the left margin. Typing -N at the : prompt toggles it without restarting, which is true of most of these flags.
Stop long lines wrapping
less -S access.log
-S (--chop-long-lines) truncates each line at the right edge instead of folding it onto the next row, so one log entry stays on one line. The arrow keys scroll sideways to read the rest.
Start at the end of the file
less +G access.log
Anything after + is a command run as the file opens, and G is the key for the last line. On a log, where the newest entry is the one you came for, that is how to open it.
Start at the first match instead
less +/500 access.log
+/pattern searches as it opens and stops on the first hit, with n for the next. Add -p in place of +/ for the same thing spelled as an option.
Follow a file as it grows
less +F /var/log/syslog
+F behaves like tail -f, printing new lines as they arrive. Ctrl-C drops back into the file where you can search and scroll, and F starts following again. tail cannot drop out of following like that.
Keep the text on screen after quitting
less -X report.txt
-X (--no-init) stops less restoring the screen on exit, so what you were reading is still in the scrollback. -F (--quit-if-one-screen) pairs with it: a file that fits on one screen is printed and less exits without waiting for q.
Keep the colours
ls --color=always -l | less -R
-R (--RAW-CONTROL-CHARS) passes ANSI colour codes through to the terminal instead of showing them as ESC[0m. Without it, any coloured output paged through less is unreadable.
less only pages when it is talking to a terminal
Give less anywhere to write other than a terminal and it stops being a pager. It copies its input to its output and exits, which is exactly what cat does.
A piped less is a cat
less report.txt | head -3
No pager, no prompt, no waiting for q. The bytes go straight down the pipe.
Show output
line 1 of the report
line 2 of the report
line 3 of the report
The display flags are dropped in silence
less -N report.txt | head -3
-N asked for line numbers and there are none. Nothing warns you, so less -N report.txt > numbered.txt writes a file identical to the input.
Show output
line 1 of the report
line 2 of the report
line 3 of the report
The options are still parsed, though
LESS=--nosuchflag less report.txt | head -2
less reads its default options from $LESS before anything else, and complains here about one that does not exist. The complaint proves the variable was read; the file is then copied through regardless.
Show output
There is no nosuchflag option ("less --help" for help)
line 1 of the report
line 2 of the report
Several files are simply joined
less report.txt access.log | sed -n '39,42p'
Interactively these are two files with :n and :p to move between them. Down a pipe they are one stream, and the join between them is invisible.
Show output
line 39 of the report
line 40 of the report
203.0.113.5 - - [13/Aug/2026:09:12:01] "GET /index.html HTTP/1.1" 200 512
203.0.113.5 - - [13/Aug/2026:09:12:03] "GET /style.css HTTP/1.1" 200 231
more is not the same
more report.txt | head -4
more prints a header naming each file even when nothing is watching, so it cannot be dropped into a pipeline the way less can. The joke that "less is more" is about the keys and the backward scrolling.
Show output
::::::::::::::
report.txt
::::::::::::::
line 1 of the report
Files less will not just show you
A file that is not there
less missing.txt
The complaint goes to standard error and no pager is started. less names the file without the less: prefix most commands put in front of an error.
Show output
missing.txt: No such file or directory
A directory
less /etc
less reads files. Use ls for what is in a directory.
Show output
/etc is a directory
Forcing it to open one anyway
gzip -n -c access.log > access.log.gz && less -f /etc | head -2
-f (--force) tells less to open anything, including a directory or a device. What comes back from a directory is not text and reads as an error.
Show output
read error
A binary file gets a question first
gzip -n -c access.log > access.log.gz && less access.log.gz | head -2
The prompt waits for y at a terminal. With nothing to answer it, less stops and prints nothing else. -f skips the question; lesspipe answers it properly.
Show output
"access.log.gz" may be a binary file. See it anyway?
Compressed files, and the hook that makes them readable
Debian ships a filter called lesspipe that less can run over a file before showing it. It handles gzip, tar, deb, PDF and a dozen other formats. It is off until you switch it on.
The direct answer for a gzipped file
gzip -n -c access.log > access.log.gz && zless access.log.gz | head -2
zless decompresses and pages in one step. A zcat, a zgrep and a zdiff sit beside it, all from the same package as gzip.
Show output
203.0.113.5 - - [13/Aug/2026:09:12:01] "GET /index.html HTTP/1.1" 200 512
203.0.113.5 - - [13/Aug/2026:09:12:03] "GET /style.css HTTP/1.1" 200 231
Or teach less to do it for every format at once
gzip -n -c access.log > access.log.gz && eval "$(lesspipe)" && less access.log.gz | head -2
lesspipe prints the two export lines that set $LESSOPEN and $LESSCLOSE. eval runs them. From then on less on a .gz, a .tar or a .deb shows you what is inside it.
Show output
203.0.113.5 - - [13/Aug/2026:09:12:01] "GET /index.html HTTP/1.1" 200 512
203.0.113.5 - - [13/Aug/2026:09:12:03] "GET /style.css HTTP/1.1" 200 231
Debian writes the hook for you and leaves it off
grep lesspipe ~/.bashrc
The line is in the .bashrc every new account starts from, commented out. Uncommenting it is the whole of the setup. It also explains why less on an archive behaves differently on two machines that look identical.
Show output
# make less more friendly for non-text input files, see lesspipe(1)
#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
Everything else that hands you to less
man pages are paged, unless nobody is watching
man ls | head -1
man runs its output through a pager. That pager makes the same terminal check less does, so piped you get the formatted page and no prompt.
Show output
LS(1) User Commands LS(1)
Choose the pager yourself
PAGER=cat man ls | head -1
$PAGER is the general setting and $MANPAGER overrides it for man alone. man --pager=cat does the same thing for one invocation.
Show output
LS(1) User Commands LS(1)
Turn the pager off where a command offers it
journalctl --no-pager -n 20
journalctl and systemctl both start less when they have a terminal, which is unhelpful in a script that only wants the text. --no-pager is their way of saying what a pipe would have said.
Check what a key does without leaving the shell
less --help | col -b | grep -E "Forward forever|Display only matching" | tr -s " \t" " "
less --help is the same list h shows from inside. It arrives with backspace overstrike for the bold, which is what col -b removes; tr then collapses the column padding.
Show output
F Forward forever; like "tail -f".
&pattern * Display only matching lines.