How to Open and View Files in Linux from the Terminal

How to Open and View Files in Linux from the Terminal

Reading time1 min
#linux#command-line#cat#less#logs

How to Open and View Files in Linux from the Terminal

"Opening a file" in Linux can mean printing it, paging through it, following a log as it grows, editing it, or launching the desktop app for it. Each has its own command.

GoalCommand
Print a short filecat
Read a long fileless
First or last lineshead, tail
Watch a growing logtail -f, less +F
Editnano, vim, sudoedit
Open in the default appxdg-open

cat: print and join files

cat /etc/os-release
cat -n script.sh                       # number the lines
cat -A config.yml                      # show tabs (^I), line ends ($), hidden characters
cat part1.sql part2.sql > all.sql      # concatenate into a new file
cat >> notes.txt                       # append typed text, Ctrl+D to finish

cat -A is the quickest way to spot a tab in a YAML file or Windows line endings, which show up as ^M$.

Two things to avoid. First, cat on a multi-gigabyte log floods the terminal; use less. Second, never redirect into one of the inputs: in cat a.txt b.txt > a.txt the shell truncates a.txt before cat starts, and its content is gone.

less: page through anything

less reads the file as you scroll instead of loading it all, so it opens huge files instantly.

less /var/log/nginx/access.log
less -N app.log            # line numbers
less -S wide.csv           # do not wrap long lines, scroll sideways
less +G app.log            # start at the end
less +F app.log            # follow mode, like tail -f

Keys inside less:

  • Space and b: page down and up
  • g and G: start and end of the file
  • /text and ?text: search forward and backward, n and N for next and previous match
  • &text: show only matching lines, & alone shows everything again
  • F: follow new lines, Ctrl+C to stop following
  • q: quit

more is the older pager. It still works, but less does everything more does and scrolls in both directions.

head and tail

head data.csv                         # first 10 lines
head -n 1 data.csv                    # header row only
tail -n 50 app.log                    # last 50 lines
tail -f app.log                       # print new lines as they arrive
tail -F app.log                       # keep following after log rotation
tail -f app.log | grep --line-buffered ERROR
sed -n '120,140p' app.log             # only lines 120 to 140
wc -l app.log                         # count lines

tail -f follows the open file, so after logrotate moves it, tail -f keeps watching the old file. tail -F reopens the path by name, which is what you want for logs.

Logs and the systemd journal

Classic log files live in /var/log: syslog and auth.log on Debian and Ubuntu, messages and secure on the RHEL family. Most of them need sudo to read. Many services on systemd hosts log only to the journal, and Debian 12 and later do not even install rsyslog by default, so /var/log/syslog may not exist there. Read the journal with journalctl:

journalctl -u nginx -e          # one service, jump to the end
journalctl -u nginx -f          # follow
journalctl -p err -b            # errors since the last boot

Open a file in an editor

nano /etc/hosts                 # simple editor, shortcuts shown at the bottom
vim +42 app.py                  # open at line 42
view /etc/ssh/sshd_config       # Vim in read-only mode
sudoedit /etc/hosts             # edit a root-owned file safely

sudoedit copies the file to a temporary location, opens it in your editor as your own user, and writes it back with root privileges when you save. Your editor settings apply and the editor itself never runs as root. It uses $SUDO_EDITOR, $VISUAL or $EDITOR. If you open Vim and cannot get out, see How to use Vim.

Open with the default desktop app

On a desktop session, xdg-open opens a file the same way a double-click in the file manager would:

xdg-open report.pdf
xdg-open .                      # current folder in the file manager
xdg-open https://example.com

On GNOME, gio open report.pdf does the same. Neither works over SSH or on a server without a graphical session.

Check what kind of file it is

Printing a binary file with cat fills the terminal with garbage and can leave it in a broken state. Check the type first:

file mystery.bin                # "ELF 64-bit executable", "gzip compressed data", ...
xxd mystery.bin | less          # hex dump
hexdump -C mystery.bin | head
strings mystery.bin | less      # readable text inside a binary

If the terminal is already garbled, type reset and press Enter, even if you cannot see what you type.

Compressed, JSON and CSV files

zcat access.log.2.gz | less
zless access.log.2.gz
zgrep ' 404 ' access.log.*.gz
jq . response.json              # pretty-print and colorize JSON
column -t -s, data.csv | less -S  # align simple CSV into columns

column does not understand quoted fields with commas inside, so treat it as a quick look, not a CSV parser.

For source code, bat adds syntax highlighting, line numbers and Git change markers. On Debian and Ubuntu the package is bat but the command is batcat, because of a name clash with another package.

Quick reference

cat file                        # print a short file
cat -A file                     # show tabs and line endings
less file                       # page through, / to search, q to quit
less +F file                    # follow a log, Ctrl+C to stop
head -n 20 file                 # first 20 lines
tail -n 50 file                 # last 50 lines
tail -F /var/log/app.log        # follow, survives rotation
journalctl -u nginx -f          # follow a service's journal
sed -n '10,20p' file            # a range of lines
sudoedit /etc/hosts             # edit a root-owned file
xdg-open file.pdf               # open in the desktop app
file unknown.bin                # what kind of file is this
zless file.gz                   # read compressed text
jq . file.json                  # pretty-print JSON