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.
| Goal | Command |
|---|---|
| Print a short file | cat |
| Read a long file | less |
| First or last lines | head, tail |
| Watch a growing log | tail -f, less +F |
| Edit | nano, vim, sudoedit |
| Open in the default app | xdg-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:
Spaceandb: page down and upgandG: start and end of the file/textand?text: search forward and backward,nandNfor next and previous match&text: show only matching lines,&alone shows everything againF: follow new lines,Ctrl+Cto stop followingq: 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
