head
and tail
— line extraction
The head
and tail
utilities can be used to obtain only
the first or last parts of a file respectively. Both will read from
the files named on the commandline, or stdin if no files are provided.
The head
utility takes a single argument, -n
, which must
be followed by an integer indicating the desired number of lines to be
displayed.
-c
option is unportable and should be avoided.
For full details, see
IEEE Std 1003.1-2017-head. Note that head(1)
on GNU systems
describes many non-portable options.
The tail
utility is similar, but takes lines from the end of the
file. The -n
argument specifies how many lines to display.
To specify "the last five lines", use tail -n 5
. To specify "all
but the first five lines", use tail -n +6
.
# bad: drop first five lines, clumsily computing line count
tail -n $(($(wc -l in.txt | awk '{print $1}') - 5)) in.txt > out.txt
# good: let tail count lines from the beginning of the file
tail -n +6 in.txt > out.txt
head/tail -5
syntax is deprecated and not POSIX compliant.
For full details, see
IEEE Std 1003.1-2017-tail. Note that tail(1)
on GNU systems
describes many non-portable options.
Chaining head
or tail
with sed
Chaining head
or tail
with sed
is usually
unnecessary. Use of addresses and early exit can do the same thing
with a single sed
call:
# bad: get the first five lines of input.txt with all 'foo'
# replaced with 'bar'
head -n 5 input.txt | sed -e 's/foo/bar/g' > output.txt
# good: use sed's address ranges and command groups to do
# the same thing with only one fork
sed -n -e '1,5{ s/foo/bar/g ; p }' input.txt > output.txt
# good: another way is with an extra command which exits
# on line 5
sed -n -e 's/foo/bar/gp ; 5q' input.txt > output.txt
# bad: set foo to the first line containing somestring
foo=$(sed -n -e '/somestring/p' input.txt | head -n 1 )
# good: use early exit to do the same thing in pure sed
foo=$(sed -n -e '/somestring/{ p ; q }' input.txt )
# bad: output the last line matching 'somestring'
sed -n -e '/somestring/p' input.txt | tail -n 1
# good: do this in pure sed using the hold space
sed -n -e '/somestring/h ; $ {x;p}'
tail -n X
where X
is larger than one is possible to do
in pure sed
but tricky. Using chained commands here is probably
simplest.
Finally, to extract a single specific line, use sed
instead:
sed -n -e '123p'