๐Ÿ”Ž Lesson 4: Reading and Searching Text

cat, head, tail, wc and grep: look inside files, and find the lines that matter

Video: Reading and Searching Text (Linux 101 video)
Prefer to watch? This short video runs the lesson's main commands on a real Ubuntu 24.04 machine, with on-screen captions and no voiceover. Click to play, or watch it on YouTube.

Why text matters so much

Almost everything on a Linux system is controlled by a plain text file: settings, user lists, logs of what happened, even the description of the operating system. That is a big reason Linux is so scriptable and so easy to inspect. If you can read text and search it, you can find out nearly anything about a machine. This lesson gives you the five tools you will use for that every single day.

Everything below was run on a real Ubuntu 24.04, using files every Ubuntu has, so you can follow along exactly. Open your practice machine.

Show a file: cat

cat prints a whole file to the screen. The name comes from "concatenate", but think of it as "show me this file".

ubuntu@practice:~$ cat /etc/hostname
practice
ubuntu@practice:~$ cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.5 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo

/etc/hostname is a one-line file with the machine's name (it said practice, the name we gave our container). /etc/os-release describes the operating system, and the first line says Ubuntu 24.04.5 LTS. This is the file the head -4 in lesson 1 read.

cat is perfect for small files. For a long one it floods the screen, and the part you wanted scrolls away. For that you have the next tools.

The start, the end and the size: head, tail and wc

ubuntu@practice:~$ head /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
ubuntu@practice:~$ head -n 3 /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
ubuntu@practice:~$ tail -n 3 /etc/passwd
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
ubuntu@practice:~$ wc -l /etc/passwd
19 /etc/passwd
ubuntu@practice:~$ wc /etc/passwd
 19  21 888 /etc/passwd

A note on what you are looking at: /etc/passwd is the list of user accounts on the machine. Each line is one account, with fields separated by colons: the name, an x (the password is kept elsewhere, in a protected file), the user and group numbers, a description, the home folder and the shell. The first line is root, the administrator, and the last is ubuntu, the account you are using.

Reading a long file a screen at a time

For a really long file you normally use a pager called less, which shows one screen at a time and lets you scroll and search. In this bare-bones practice container it is not installed, and the shell says so:

ubuntu@practice:~$ less /etc/passwd
bash: less: command not found

That is the expected result here, and it is a good example of an error that does not mean you did something wrong: the program simply is not on this machine. Lesson 6 shows you how to install software, and less will be one of the first things we install. On a normal Ubuntu (WSL, a virtual machine, a real computer) it is already there, and you use it like this, from the documentation, not run here: less FILE opens the file, the Space bar moves down a page, b moves back up, /word searches for a word, and q quits.

Find the lines that matter: grep

grep is the single most useful text tool you will learn. It reads a file and prints only the lines that contain what you are looking for. The name is old Unix shorthand for "search globally for a regular expression and print", and nobody expects you to remember that.

ubuntu@practice:~$ grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
ubuntu@practice:~$ grep -n root /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
ubuntu@practice:~$ grep ROOT /etc/passwd
ubuntu@practice:~$ grep -i ROOT /etc/passwd
root:x:0:0:root:/root:/bin/bash
ubuntu@practice:~$ grep -c nologin /etc/passwd
16
ubuntu@practice:~$ grep -v nologin /etc/passwd
root:x:0:0:root:/root:/bin/bash
sync:x:4:65534:sync:/bin:/bin/sync
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash

Search several files, and files you cannot read

ubuntu@practice:~$ grep -l root /etc/passwd /etc/group /etc/hostname
/etc/passwd
/etc/group
ubuntu@practice:~$ grep -rl ubuntu /etc/apt
/etc/apt/sources.list
/etc/apt/trusted.gpg.d/ubuntu-keyring-2012-cdimage.gpg
/etc/apt/trusted.gpg.d/ubuntu-keyring-2018-archive.gpg
/etc/apt/sources.list.d/ubuntu.sources
ubuntu@practice:~$ cat /etc/shadow
cat: /etc/shadow: Permission denied
ubuntu@practice:~$ ls -l /etc/shadow /etc/passwd
-rw-r--r-- 1 root root   888 Sep 17 02:29 /etc/passwd
-rw-r----- 1 root shadow 502 Sep 17 02:29 /etc/shadow

Find files by name: find

grep searches inside files. find searches for files by name, and by other properties:

ubuntu@practice:~$ find /usr/share/common-licenses -name "GPL*"
/usr/share/common-licenses/GPL-2
/usr/share/common-licenses/GPL-1
/usr/share/common-licenses/GPL-3
/usr/share/common-licenses/GPL
ubuntu@practice:~$ find /usr/share/common-licenses -name "*2*"
/usr/share/common-licenses/GPL-2
/usr/share/common-licenses/GFDL-1.2
/usr/share/common-licenses/Apache-2.0
/usr/share/common-licenses/LGPL-2
/usr/share/common-licenses/LGPL-2.1
/usr/share/common-licenses/MPL-2.0
ubuntu@practice:~$ find /etc -name "host*"
/etc/host.conf
/etc/hostname
/etc/hosts
ubuntu@practice:~$ find /etc/security -name "*.conf" -type f
/etc/security/faillock.conf
/etc/security/group.conf
/etc/security/namespace.conf
/etc/security/pam_env.conf
/etc/security/pwhistory.conf
/etc/security/time.conf
/etc/security/limits.conf
/etc/security/sepermit.conf
/etc/security/access.conf

Did it find anything? The exit status

Every command leaves behind a small number saying whether it succeeded, called its exit status. Zero means success. grep uses a non-zero number to mean "no matches". You can see it with echo $?, which prints the status of the last command:

ubuntu@practice:~$ grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
ubuntu@practice:~$ echo $?
0
ubuntu@practice:~$ grep zzz /etc/passwd
ubuntu@practice:~$ echo $?
1

After a successful search the status is 0. After a search with no matches it is 1. You will not need this today, but it is the reason scripts can ask "did grep find anything?", and you will use it in lesson 11.

Why did the Linux user get lost in the forest?<br>
Because they kept typing <span class="command">cat</span> to find the cat, and all they got was a file.

๐Ÿงช Try it yourself

1. Show the first 5 lines of /etc/passwd. 2. How many lines does /etc/os-release have? (Use one command.) 3. Which line of /etc/os-release contains the word Noble? Show the line number too. 4. Find every file under /usr/share/common-licenses whose name contains Apache. 5. List the accounts in /etc/passwd that are not nologin accounts.

The cheat sheet

← Lesson 3 · ↑ All lessons · Lesson 5: Users, Permissions and sudo →