unix - head AND tail of file
You can simply:
(head; tail) < file.txt
And if you need to uses pipes for some reason then like this:
cat file.txt | (head; tail)
Note: will print duplicated lines if number of lines in file.txt is smaller than default lines of head + default lines of tail.
How does (head; tail) file work?
OS X
For OS X, you can look at the source code for head
and the source code for tail
to figure out some of what's going on. In the case of tail
, you'll want to look at forward.c
.
So, it turns out that head
doesn't do anything special. It just reads its input using the stdio
library, so it reads a buffer at a time and might read too much. This means cat file | (head; tail)
won't work for small files where head
's buffering makes it read some (or all) of the last 10 lines.
On the other hand, tail
checks the type of its input file. If it's a regular file, tail
seeks to the end and reads backwards until it finds enough lines to emit. This is why (head; tail) < file
works on any regular file, regardless of size.
Linux
You could look at the source for head
and tail
on Linux too, but it's easier to just use strace
, like this:
(strace -o /tmp/head.trace head; strace -o /tmp/tail.trace tail) < file
Take a look at /tmp/head.trace
. You'll see that the head
command tries to fill a buffer (of 8192 bytes in my test) by reading from standard input (file descriptor 0). Depending on the size of file
, it may or may not fill the buffer. Anyway, let's assume that it reads 10 lines in that first read. Then, it uses lseek
to back up the file descriptor to the end of the 10th line, essentially “unreading” any extra bytes it read. This works because the file descriptor is open on a normal, seekable file. So (head; tail) < file
will work for any seekable file, but it won't make cat file | (head; tail)
work.
On the other hand, tail
does not (in my testing) seek to the end and read backwards, like it does on OS X. At least, it doesn't read all the way back to the beginning of the file.
Here's my test. Create a small, 12-line input file:
yes | head -12 | cat -n > /tmp/file
Then, try (head; tail) < /tmp/file
on Linux. I get this with GNU coreutils 5.97:
1 y
2 y
3 y
4 y
5 y
6 y
7 y
8 y
9 y
10 y
11 y
12 y
But on OS X, I get this:
1 y
2 y
3 y
4 y
5 y
6 y
7 y
8 y
9 y
10 y
3 y
4 y
5 y
6 y
7 y
8 y
9 y
10 y
11 y
12 y
How do I use Head and Tail to print specific lines of a file
Aside from the answers given by fedorqui and Kent, you can also use a single sed
command:
#!/bin/sh
filename=$1
firstline=$2
lastline=$3
# Basics of sed:
# 1. sed commands have a matching part and a command part.
# 2. The matching part matches lines, generally by number or regular expression.
# 3. The command part executes a command on that line, possibly changing its text.
#
# By default, sed will print everything in its buffer to standard output.
# The -n option turns this off, so it only prints what you tell it to.
#
# The -e option gives sed a command or set of commands (separated by semicolons).
# Below, we use two commands:
#
# ${firstline},${lastline}p
# This matches lines firstline to lastline, inclusive
# The command 'p' tells sed to print the line to standard output
#
# ${lastline}q
# This matches line ${lastline}. It tells sed to quit. This command
# is run after the print command, so sed quits after printing the last line.
#
sed -ne "${firstline},${lastline}p;${lastline}q" < ${filename}
Or, to avoid any external utilites, if you're using a recent version of bash (or zsh):
#!/bin/sh
filename=$1
firstline=$2
lastline=$3
i=0
exec <${filename} # redirect file into our stdin
while read ; do # read each line into REPLY variable
i=$(( $i + 1 )) # maintain line count
if [ "$i" -ge "${firstline}" ] ; then
if [ "$i" -gt "${lastline}" ] ; then
break
else
echo "${REPLY}"
fi
fi
done
Using combination of head and tail to display middle line of the file in Unix
head -2 myownfile | tail -1
should do what you want
head and tail on Unix
Use head
to extract the first 53 lines. Use tail
to extract the last 51 lines of the result (effectively ignoring the first 2 header lines).
Using Linux commands head and tail
tail
command also comes with an +
option which is not present in the head command. With this option tail command prints, the data starting from the specified line number of the file instead of the end.
For command: tail +n file_name
, data will start printing from line number n
till the end of the file
Let's say we have file file.txt
Hello from localhost1
Hello from localhost2
Hello from localhost3
Hello from localhost4
Hello from localhost5
Hello from localhost6
If you will use tail with +
option then tail
will start from the specified number like below :
head -n 4 file.txt | tail -n +1
Hello from localhost1
Hello from localhost2
Hello from localhost3
Hello from localhost4
Starts from 2nd line :
head -n 4 file.txt | tail -n +2
Hello from localhost2
Hello from localhost3
Hello from localhost4
Starts from 3rd line :
head -n 4 file.txt | tail -n +3
Hello from localhost3
Hello from localhost4
Starts from 4th line :
head -n 4 file.txt | tail -n +4
Hello from localhost4
That is the reason it's giving the same output as head -n 4 file.txt | tail -n 1
+
and -
both have a different meaning in tail
.
Related Topics
How to Specify More Spaces for the Delimiter Using Cut
Send Mail from Linux Terminal in One Line
Location of Ini/Config Files in Linux/Unix
How to Download a Tarball from Github Using Curl
Truncating a File While It's Being Used (Linux)
How to Undo Strip - I.E. Add Symbols Back to Stripped Binary
Maximum Number of Bash Arguments != Max Num Cp Arguments
How to Use Gdb to Debug a Running Process
Why Doesn't "Total" from Ls -L Add Up to Total File Sizes Listed
How to Program Linux .Dts Device Tree Files
User-Data Scripts Is Not Running on My Custom Ami, But Working in Standard Amazon Linux
How to Set a Custom Baud Rate on Linux
Run Script with Rc.Local: Script Works, But Not at Boot
How to Sort a File, Based on Its Numerical Values for a Field
How to Get the Difference (Only Additions) Between Two Files in Linux
What Is the Correct Way to Start a Mongod Service on Linux/Os X
How to Modify the Source of Buildroot Packages for Package Development