CoursesLinux essentialsViewing & editing files

Viewing & editing files

cat, less, head, tail, wc, nano, vim.

Beginner14 min · lesson 5 of 25

A server is a filing cabinet you reach through a keyhole. There is no mouse, no window to double-click open. You get a text screen, a blinking cursor, and files: the configuration that tells each program how to behave, the logs that record everything it did, the scripts that run on their own schedule. Reading those files is most of the job. Changing one, now and then, is the rest.

You are learning this to do DevSecOps work (development, security, and operations rolled into one role), and the pattern shows up on your first bad day. Something looks wrong. A site is slow, a login keeps failing, an alert just fired. The first move is always to open a file and read it: a log to see what happened, a config to see what the machine was told to do. Pick the wrong command and you drown in output or garble your screen. Pick the right one and the problem is sitting there in front of you. Here is the small set that covers every case.

cat: Tip the Whole File Out

cat tips the whole envelope onto the table. It prints a file's entire contents to the screen in one shot and hands your prompt back. The name is short for concatenate (to join things end to end), because if you give it several files it prints them one after another. It is perfect for a short file and painful for a long one, since a big file scrolls past faster than you can read it.

~/secopslog — bash
$ cat /etc/hostname
web-01

Add -n and it numbers every line, which helps when a program complains about an error on line 14 and you want to find line 14. Here is the file that controls how this machine looks up names on the network:

~/secopslog — bash
$ cat -n /etc/resolv.conf
1 # Managed by systemd-resolved(8). Do not edit by hand. 2 nameserver 127.0.0.53 3 options edns0 trust-ad 4 search example.com

That 127.0.0.53 is a local stub resolver, part of DNS (the Domain Name System, the internet's phone book that turns names like example.com into numeric addresses). If that nameserver line ever points somewhere you do not recognize, someone may be quietly redirecting the machine's traffic, and reading this one file is how you would catch it.

cat only belongs on text
A file full of non-text bytes (a program binary, or a log line an attacker managed to write) gets sent to your terminal raw. Some byte sequences are not letters, they are instructions to the terminal itself: move the cursor, change the window title, on some terminals remap a key. A booby-trapped log entry can scramble your screen or hide text from you. If you are not certain a file is plain text, open it with less (which shows those bytes as visible codes like ^[) or run cat -v to make them printable.

less: Page Through Anything Long

less reads a long document one screen at a time, with a bookmark and a search box, instead of dumping every page on the floor. It is a pager (a program that shows one screenful and lets you move around inside the file). It opens huge files instantly because it only reads the part you are looking at, never the whole thing at once. This is the tool for anything longer than your screen. System logs live under /var/log and are usually readable only by the administrator, so you open them with sudo in front (sudo, short for super-user do, runs a single command with administrator powers):

~/secopslog — bash
$ sudo less /var/log/syslog
Jul 17 08:00:12 web-01 systemd[1]: Started Daily apt download activities. Jul 17 08:01:01 web-01 systemd[1]: Starting Rotate log files... Jul 17 08:01:02 web-01 systemd[1]: logrotate.service: Deactivated successfully. Jul 17 08:17:33 web-01 systemd[1]: Started Session 42 of User deploy. :

That colon at the bottom is the less prompt, waiting for you. Space and b move down and up a page, the arrow keys nudge one line, /error searches forward for the word error (press n for the next match), G jumps to the end, g to the top, and q quits. Two more commands earn their keep on logs. Type &sshd and Enter to hide every line that does not contain sshd, so you see only the SSH events (SSH, or Secure Shell, is the encrypted channel you use to log into a machine over the network). Press Shift-F and less starts following the file live, printing new lines as they land; press Ctrl-C to stop following and go back to scrolling.

head and tail: The Top and the Bottom

A letter has a top and a bottom. head reads the first lines of a file, tail reads the last. By default each shows ten lines, and -n N asks for exactly N. You will reach for tail far more often, because logs grow downward: the newest events, the ones you care about during an incident, are always at the bottom.

~/secopslog — bash
$ sudo head -n 3 /var/log/nginx/access.log
10.0.1.5 - - [17/Jul/2026:08:14:02 +0000] "GET /health HTTP/1.1" 200 2 10.0.1.9 - - [17/Jul/2026:08:14:03 +0000] "GET /api/users HTTP/1.1" 200 1834 10.0.1.9 - - [17/Jul/2026:08:14:05 +0000] "POST /api/login HTTP/1.1" 401 43

That file is the access log for nginx (a popular web server, the program that takes requests from browsers and sends back pages). Those three-digit numbers near the end of each line are HTTP status codes (HTTP, HyperText Transfer Protocol, is the language browsers and servers speak): 200 means the request worked, 401 means it was rejected for bad credentials, 500 would mean the server itself broke. A wall of 401s on the login route is what a password-guessing attack looks like from the web server's side.

The real power move is tail -f, where -f means follow. The command stays open and prints each new line the instant it is written, so you can watch a log live while you reproduce a problem, or watch an attack as it happens. The login records are private, so you read this one with sudo too. This is the authentication log, the file that records every login attempt on the machine:

~/secopslog — bash
$ sudo tail -f /var/log/auth.log
Jul 17 09:14:02 web-01 sshd[2841]: Failed password for invalid user admin from 203.0.113.45 port 51124 ssh2 Jul 17 09:14:03 web-01 sshd[2841]: Failed password for invalid user admin from 203.0.113.45 port 51126 ssh2 Jul 17 09:14:05 web-01 sshd[2843]: Failed password for root from 203.0.113.45 port 51140 ssh2 Jul 17 09:14:07 web-01 sshd[2843]: Connection closed by invalid user oracle 203.0.113.45 port 51142 [preauth]

Line after line of Failed password from a single address, trying admin, then root (the all-powerful administrator account), then oracle, is a brute-force attempt (a program guessing usernames and passwords over and over). Watching it scroll is how you catch it while it is still happening. Press Ctrl-C to stop following.

wc: How Many?

wc is the clicker a doorman uses to count people coming in. Short for word count, on its own it prints three numbers for a file: lines, words, and bytes. The flag you will use nearly every time is -l, which counts lines. Joined to another command with a pipe (the | symbol, which feeds one command's output straight into the next), it answers how many faster than you could ever count by hand.

~/secopslog — bash
$ sudo wc -l /var/log/auth.log
15847 /var/log/auth.log

Most of the time you want a count of one specific thing, not the whole file. That is where grep earns its place. grep (a search command that prints only the lines matching a word or pattern) filters the file first, then wc counts what survived:

~/secopslog — bash
$ sudo grep "Failed password" /var/log/auth.log | wc -l
1934

Nineteen hundred failed passwords in one log file is not background noise. That is someone hammering on the door. And that single number, watched over time, is one of the cheapest security signals you have: when it jumps, you look closer.

Which command do you reach for?
You need to look inside a file
whole short file
cat
dumps it all at once
long file, read or search
less
pager; opens instantly, / to search
only the first lines
head -n N
the top of the file
the end, or watch it live
tail -f
newest lines; follows as they arrive
only a count
wc -l
how many lines, often after grep

nano and vim: Changing a File

Reading is most of the work, but sooner or later you have to change a file, and for that you need an editor that lives in the terminal, because a server has no graphical one. Two of them turn up everywhere.

nano is the friendly one. It works the way you expect: you type, the text appears, the arrow keys move around. Along the bottom it lists its own shortcuts, where the ^ symbol means the Ctrl key. So Ctrl-O writes the file out (saves it) and Ctrl-X exits. That is almost everything you need. Say you are tightening how people log in, inside the SSH server's configuration file:

/etc/ssh/sshd_config
# /etc/ssh/sshd_config (excerpt)
Port 22
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

Those four lines are a real security decision. root cannot log in directly, passwords are turned off entirely, and only cryptographic keys are accepted. You open the file, make the change, and save:

~/secopslog — bash
$ sudo nano /etc/ssh/sshd_config # type your change normally # ^O save (write out) # ^X exit

vim is the other one. Some version of it, vim or its older sibling vi, sits on effectively every Unix and Linux machine you will meet, so you cannot dodge it forever. It is modal, which trips up everyone at first. A normal editor is always ready for you to type. vim starts in normal mode, where the letter keys are commands, not text. You press i to enter insert mode (now you can type), Esc to leave it, and back in normal mode you type :wq to write and quit, or :q! to quit and throw away your changes.

~/secopslog — bash
$ sudo vim /etc/ssh/sshd_config # i insert mode (start typing) # Esc back to normal mode # :wq save and quit # :q! quit and discard changes

One habit matters more than which editor you pick. After you change a config that a running service depends on, check it before you restart anything. For the SSH server, sshd -t reads the file and tells you whether you broke it:

~/secopslog — bash
$ sudo sshd -t
/etc/ssh/sshd_config: line 3: Bad configuration option: PermtiRootLogin /etc/ssh/sshd_config: terminating, 1 bad configuration options

That typo, PermtiRootLogin instead of PermitRootLogin, was caught before it did any harm. Restart SSH on a remote machine with a broken config and the service can fail to come back up, and now you are locked out of your own server with no way in. Test first. And whenever you change how you log in, keep a second SSH session open in another window until you have proven the new setting works. It is your rope back through the keyhole.

One more escape hatch, because everyone gets stuck in vim at least once. You open a file, type a little, and the keys stop doing what you expect with no obvious way out. Press Esc to make sure you are in normal mode, then type :q! and Enter to quit without saving, or :wq if you want to keep your changes. That one sequence works on the vi and vim that ship with effectively every Linux and Unix system. Memorize it before you need it, not during.

Quick check
01A brute-force attack may be underway and you want to watch SSH login attempts appear in real time as they happen. Which command do you run?
Correct — -f follows the file and prints each new line the moment it is written.
Incorrect — cat prints the file once and stops. It never shows lines added after it ran.
Incorrect — Plain less shows a static snapshot. You would need to press Shift-F to make it follow like tail -f.
Incorrect — wc only counts lines. It tells you how many, not what they say, and does not update live.
02The lesson warns against running cat on a file that might not be plain text. What is the specific danger it describes?
Incorrect — reading a file with cat does not modify it; the risk is what the bytes do to your terminal.
Incorrect — cat only prints bytes, it does not run them as programs.
Correct — raw non-text bytes can be instructions to the terminal itself, which is why the lesson prefers less or cat -v.
Incorrect — the concern is terminal control sequences, not speed or freezing.
03You edited /etc/ssh/sshd_config on a remote server over SSH. Before running systemctl restart ssh, the lesson says to run sudo sshd -t first. Why does that step matter so much here?
Incorrect — sshd -t validates the config, it does not reload or restart the service.
Correct — the lesson's whole point is to catch a typo before a restart strands you outside your own server.
Incorrect — sshd -t performs a syntax test, it does not encrypt anything.
Incorrect — nothing validates the config automatically, so every edit should be tested before a restart.

Build one habit above the rest. On a machine you are investigating, treat every log as something an attacker may have written into, and read it with less, not cat. The pager shows you the raw bytes safely and never hands control of your terminal over to the file. That caution is the difference between reading the evidence and becoming part of the incident.

Try this

Work through “nano and vim: Changing a File” yourself on a sandbox you can throw away, following the commands above in order. Then break one step deliberately and re-run, so you have seen the failure before it finds you.

Takeaway

The trap worth remembering here: cat only belongs on text. Check that on your own systems before you need to, because it is cheaper to find on a quiet afternoon than during an incident.

Related