Filtering based on lines—head and tail

To display the content of a file, we will use the cat command. The cat command displays the whole file content on stdout. However, sometimes, we are interested in viewing only a few lines of a file. In this case, using cat will be tedious because we will have to scroll down to particular lines that we are interested in.

Shell provides us the head and tail commands to print only the lines in which we are interested in. The main difference between both the commands is, head prints the lines from the beginning of the files, and tail prints the lines from the end of the files.

Printing lines using head

The syntax is as follows:

head [OPTION] [FILE …]

By default, head prints first 10 lines of each FILE to stdout. If no file is mentioned or '-' is specified, the input is taken from stdin.

The options available in head can be used to change how much of the content to be printed. The options available are described in the following table:

Option

Description

-c [-] K

This prints first K bytes of a file. If -K is used, then you can output all contents except the last K bytes.

-n [-]K

This prints first K lines of each file. If -K is used, then you can output all lines except the last n lines.

-q

This prevents name of input files from being printed.

-v

This always outputs the header having the filename of each file.

Printing the first few lines

Let's see how many files /usr/lib64/ directory contains -:

$ ls /usr/lib64 | wc
3954

We see that /usr/lib64 has 3954 files. Suppose, we don't want all the libraries names, but just the first five library names. We can use a head command for this as follows:

$ ls /usr/lib64 | head -n 5
akonadi
alsa-lib
ao
apper
apr-util-1

Printing the first few bytes

We use the -c option to print the first few bytes of a file, as follows:

$  head -c50 /usr/share/dict/linux.words /usr/share/dict/words
==> /usr/share/dict/linux.words <==
1080
10-point
10th
11-point
12-point
16-point
18-p
==> /usr/share/dict/words <==
1080
10-point
10th
11-point
12-point
16-point
18-p

This first prints 50 bytes of the /usr/share/dict/linux.words and /usr/share/dict/words files.

We can eliminate the printing of the header having a filename using –q:

$ head -c50 -q  /usr/share/dict/linux.words /usr/share/dict/words
1080
10-point
10th
11-point
12-point
16-point
18-p1080
10-point
10th
11-point
12-point
16-point
18-p

For a single file, command head doesn't print name of file in output. To see it, use –v option:

$ head -c50 -v  /usr/share/dict/linux.words
==> /usr/share/dict/linux.words <==
1080
10-point
10th
11-point
12-point
16-point
18-p

Printing lines using tail

The syntax for tail is as follows:

tail [OPTION] [FILE …]

By default, tail prints the last 10 lines of each FILE to stdout. If no file is mentioned or '-' is specified, the input is taken from stdin.

The options available in tail can be used to change how much of the content to be printed. The available options are described in the following table:

Option

Description

-c [+]K

This prints the last K byte of each file. If +K is used, then print from Kth byte of each file.

-n [+]K

This prints the last K lines of each file. If +K is used, then output from Kth line of each file.

-f [{name|descriptor}]

The outputs the appended data as the file grows.

--retry

This keeps trying to open a file if it is inaccessible.

--max-unchanged-stats=N

With the -f name, reopen the file that has not opened. This shows the changed size after N iterations (default 5).

--pid=PID

With -f, terminate if PID dies.

-q

Don't output header having filename of each file.

-F

This is the same as the -f name --retry option.

-s N

This sleeps for N seconds between iterations. With –pid=PID, check the process at least once in N seconds.

-v

This always outputs the header having a filename of each file.

Checking log entries

The tail command is frequently used to check the error or message log for the last few run of commands. With each new run, logs are appended at the end of the line.

We will see in following example that kernel log entries are made when a new USB drive is added and when it is removed:

$ dmesg | tail -n7    # Log when USB was attached
[120060.536856] sd 10:0:0:0: Attached scsi generic sg1 type 0
[120060.540848] sd 10:0:0:0: [sdb] 1976320 512-byte logical blocks: (1.01 GB/965 MiB)
[120060.541989] sd 10:0:0:0: [sdb] Write Protect is off
[120060.541991] sd 10:0:0:0: [sdb] Mode Sense: 23 00 00 00
[120060.543125] sd 10:0:0:0: [sdb] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
[120060.550464]  sdb: sdb1
[120060.555682] sd 10:0:0:0: [sdb] Attached SCSI removable disk
$ dmesg | tail -n7  # USB unmounted
[120060.540848] sd 10:0:0:0: [sdb] 1976320 512-byte logical blocks: (1.01 GB/965 MiB)
[120060.541989] sd 10:0:0:0: [sdb] Write Protect is off
[120060.541991] sd 10:0:0:0: [sdb] Mode Sense: 23 00 00 00
[120060.543125] sd 10:0:0:0: [sdb] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
[120060.550464]  sdb: sdb1
[120060.555682] sd 10:0:0:0: [sdb] Attached SCSI removable disk
[120110.466498] sdb: detected capacity change from 1011875840 to 0

We saw that when USB was unmounted, a new log entry was added:[120110.466498] sdb: detected capacity change from 1011875840 to 0 To check the last 10 yum logs in an RPM-based system, we can do the following:

#  sudo tail -n4 -v /var/log/yum.log
==> /var/log/yum.log-20150320 <==
Mar 19 15:40:19 Updated: libgpg-error-1.17-2.fc21.i686
Mar 19 15:40:19 Updated: libgcrypt-1.6.3-1.fc21.i686
Mar 19 15:40:20 Updated: systemd-libs-216-21.fc21.i686
Mar 19 15:40:21 Updated: krb5-libs-1.12.2-14.fc21.i686

To see real-time logs, we can use the -f option. For example, the /var/log/messages file shows the general system activities. With tail -f, appended log messages in /var/log/messages will be printed on stdout as well:

$ tail -f /var/log/messages
Jun  7 18:21:14 localhost dbus[667]: [system] Rejected send message, 10 matched rules; type="method_return", sender=":1.23" (uid=0 pid=1423 comm="/usr/lib/udisks2/udisksd --no-debug ") interface="(unset)" member="(unset)" error name="(unset)" requested_reply="0" destination=":1.355" (uid=1000 pid=25554 comm="kdeinit4: dolphin [kdeinit] --icon system-fil   ")
Jun  7 18:21:14 localhost systemd-udevd: error: /dev/sdb: No medium found
Jun  7 18:21:14 localhost systemd-udevd: error: /dev/sdb: No medium found
Jun  7 18:27:10 localhost kernel: [135288.809319] usb 3-1.2: USB disconnect, device number 14
Jun  7 18:27:10 localhost kernel: usb 3-1.2: USB disconnect, device number 14
Jun  7 18:27:10 localhost systemd-udevd: error opening USB device 'descriptors' file

The command prompt won't return back. Instead, the output will keep getting updated whenever there is new content in /var/log/messages.

Finding any line in a file

We can use head and tail to find any line of a file.

We will consider the /usr/share/dict/words file as an example.

Now, to find the 10th line of this file, we can do the following:

$ head -10 /usr/share/dict/words | tail -n1  # 10th line
20-point

$ head -200000 /usr/share/dict/words | tail -n1  #  200000th line
intracartilaginous
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.73.77