head and tail
cat
is useful to view entire contents of file(s). Pagers like less
can be used if you are working with large files (man
pages for example). Sometimes though, you just want a peek at the starting or ending lines of input files. Or, you know the line numbers for the information you are looking for. In such cases, you can use head
or tail
or a combination of both these commands to extract the content you want.
Leading and trailing lines
Consider this sample file, with line numbers prefixed for convenience.
$ cat sample.txt
1) Hello World
2)
3) Hi there
4) How are you
5)
6) Just do-it
7) Believe it
8)
9) banana
10) papaya
11) mango
12)
13) Much ado about nothing
14) He he he
15) Adios amigo
By default, head
and tail
will display the first and last 10 lines respectively.
$ head sample.txt
1) Hello World
2)
3) Hi there
4) How are you
5)
6) Just do-it
7) Believe it
8)
9) banana
10) papaya
$ tail sample.txt
6) Just do-it
7) Believe it
8)
9) banana
10) papaya
11) mango
12)
13) Much ado about nothing
14) He he he
15) Adios amigo
If there are less than 10 lines in the input, only those lines will be displayed.
# seq command will be discussed in detail later, generates 1 to 4 here
# same as: seq 4 | tail
$ seq 4 | head
1
2
3
4
You can use the -nN
option to customize the number of lines (N
) needed.
# first three lines
# space between -n and N is optional
$ head -n3 sample.txt
1) Hello World
2)
3) Hi there
# last two lines
$ tail -n2 sample.txt
14) He he he
15) Adios amigo
Excluding the last N lines
By using head -n -N
, you can get all the input lines except the ones you'll get when you use the tail -nN
command.
# except the last 11 lines
# space between -n and -N is optional
$ head -n -11 sample.txt
1) Hello World
2)
3) Hi there
4) How are you
Starting from Nth line
By using tail -n +N
, you can get all the input lines except the ones you'll get when you use the head -n(N-1)
command.
# all lines starting from the 11th line
# space between -n and +N is optional
$ tail -n +11 sample.txt
11) mango
12)
13) Much ado about nothing
14) He he he
15) Adios amigo
Multiple input files
If you pass multiple input files to the head
and tail
commands, each file will be processed separately. By default, the output is nicely formatted with filename headers and empty line separators.
$ seq 2 | head -n1 greeting.txt -
==> greeting.txt <==
Hi there
==> standard input <==
1
You can use the -q
option to avoid filename headers and empty line separators.
$ tail -q -n2 sample.txt nums.txt
14) He he he
15) Adios amigo
42
1000
Byte selection
The -c
option works similar to the -n
option, but with bytes instead of lines. In the below examples, newline characters have been added to the output for illustration purposes.
# first three characters
$ printf 'apple pie' | head -c3
app
# last three characters
$ printf 'apple pie' | tail -c3
pie
# excluding last four characters
$ printf 'car\njeep\nbus\n' | head -c -4
car
jeep
# all characters starting from fifth character
$ printf 'car\njeep\nbus\n' | tail -c +5
jeep
bus
Since -c
works byte wise, it may not be suitable for multibyte characters:
# all input characters in this example occupy two bytes each
$ printf 'αλεπού' | head -c2
α
# g̈ occupies three bytes
$ printf 'cag̈e' | tail -c4
g̈e
Range of lines
You can select a range of lines by combining both head
and tail
commands.
# 9th to 11th lines
# same as: head -n11 sample.txt | tail -n3
$ tail -n +9 sample.txt | head -n3
9) banana
10) papaya
11) mango
# 6th to 7th lines
# same as: tail -n +6 sample.txt | head -n2
$ head -n7 sample.txt | tail -n2
6) Just do-it
7) Believe it
See unix.stackexchange: line X to line Y on a huge file for performance comparison with other commands like
sed
,awk
, etc.
NUL separator
The -z
option sets the NUL character as the line separator instead of the newline character.
$ printf 'car\0jeep\0bus\0' | head -z -n2 | cat -v
car^@jeep^@
$ printf 'car\0jeep\0bus\0' | tail -z -n2 | cat -v
jeep^@bus^@