Your First Hour in the Linux Terminal: Navigating it

The CyberSec Guru

Navigating the Linux Terminal

If you like this post, then please share it:

Buy me A Coffee!

Support The CyberSec Guru’s Mission

🔐 Fuel the cybersecurity crusade by buying me a coffee! Why your support matters: Zero paywalls: Keep the main content 100% free for learners worldwide.

“Your coffee keeps the servers running and the knowledge flowing in our fight against cybercrime.”☕ Support My Work

Buy Me a Coffee Button

This is post 1 of 1 in the series “Linux Handbook CLI”

The first time you SSH into a headless Ubuntu server, there is nothing to click. No window manager, no file tree in a sidebar, no hover state warning you before you do something destructive. You get a blank screen, a prompt like thecybersecguru@thecybersecguru:~$, and a block cursor waiting for input. Plenty of new administrators freeze here because nothing tells them where they are or what they are allowed to type.

Three navigation commands (pwd, ls, and cd) and two built-in documentation systems (--help and man) are enough to fix that. With them you can orient yourself on any unfamiliar server, read file metadata down to the inode, and look up any tool on the machine without opening a browser.

Course Video Under Progress

We’re working on the video lessons. They’ll be dropping shortly. Stay tuned!

Coming Soon

How to read the Ubuntu Server prompt

That one line already carries four pieces of context. thecybersecguru is your username. thecybersecguru after the @ is the machine’s hostname. The ~ after the colon is your current location, shorthand for your home directory. The trailing $ means you are an unprivileged user; a # would mean you are the superuser. Once you can read that line, the terminal stops feeling like a black box.

The Blinky Cursor in the Linux Terminal
The Blinky Cursor in the Linux Terminal

How to find your location with the pwd command

Every operation on a Unix-like system happens relative to a place in the directory tree, which the kernel calls the process’s current working directory. Each running process, including your interactive Bash shell, keeps pointers to the filesystem root and to its working directory in its kernel task structure (fs_struct). Type pwd (print working directory) and the shell writes your full absolute path to standard output, starting from the root slash:

thecybersecguru@thecybersecguru:~$ pwd
/home/thecybersecguru

You might ask why you need a command when the prompt already shows ~. In production, trusting the prompt is a bad habit. Its appearance is controlled by the PS1 environment variable, and many administrators set it with \W instead of \w, which shows only the last folder name so deep paths do not wrap across three lines. Minimal recovery shells such as dash or an emergency initramfs shell may show nothing more than a bare $ or (initramfs). Running pwd skips prompt formatting entirely and gives you the exact path from root.

The pwd Command
The pwd Command

pwd -L vs pwd -P: logical and physical paths

pwd also has to deal with symbolic links. Say /var/www is a symlink pointing to /mnt/storage/web_data, and you cd into /var/www. Logically, you walked through /var/www, and your shell keeps that breadcrumb in the $PWD variable. Physically, the kernel put your process inside the inode for /mnt/storage/web_data.

By default pwd runs in logical mode (the same as pwd -L). It reads $PWD and prints /var/www, matching the path you typed. If you are debugging storage mounts, or writing a deployment script that needs the real underlying path, use pwd -P. That flag ignores $PWD and calls getcwd(), which walks upward through the parent entries (..) in the virtual filesystem (VFS) until it reaches the root inode, then returns /mnt/storage/web_data.

📬 Stay Ahead of Cyber Threats

Get the latest cybersecurity news, critical vulnerabilities, threat intelligence, tutorials, and exclusive giveaways delivered straight to your inbox. No spam. Unsubscribe anytime.

Subscribe to the Newsletter →

How to list files with the ls command

Knowing your directory is only useful once you can see what is in it. Run ls with no arguments and it reads the entries of the current directory and prints their names in alphabetical columns. In Linux, a directory is a special file holding a table that maps filenames to inode numbers.

To check that you can write to a folder, and to watch ls reflect a change, run touch test.txt and then ls. If test.txt does not exist, touch makes an openat() system call with the O_CREAT flag to allocate an empty file, then calls utimensat() to set its access and modification timestamps to the current clock. A second later, ls shows the new file.

Reading ls -l output

Bare filenames rarely tell you enough to troubleshoot a server, so experienced operators reach for ls -l, the long listing format, almost by reflex. With -l, ls can no longer just read the directory table. It runs stat() (or lstat() for symlinks) alongside getxattr() on every entry to pull metadata from each file’s inode. The result is a dense, seven-column readout:

thecybersecguru@thecybersecguru:~$ touch test.txt
thecybersecguru@thecybersecguru:~$ ls -l
total 0
-rw-rw-r-- 1 thecybersecguru thecybersecguru 0 Nov 3 18:20 test.txt
The ls -l Command Output
The ls -l Command Output

Every character in that output means something. The total 0 line reports the disk blocks allocated to the listed files, not the number of files. On the next line, the ten-character string -rw-rw-r-- breaks into four parts.

The first character is the file type: - for a regular file, d for a directory, l for a symbolic link, c for a character device such as a terminal or serial port, and b for a block device such as a disk partition. The other nine characters are three triplets of read (r), write (w), and execute (x) permissions, for the file’s user owner (rw-), its group owner (rw-), and everyone else (r--).

Next is the hard link count, 1, the number of directory entries across the filesystem that point to this inode. A regular file normally has 1. A directory has at least 2: its own entry in its parent, plus the . entry inside itself. Each subdirectory adds one more, because its .. entry points back to the parent.

After the link count come the owner (thecybersecguru) and group (thecybersecguru), resolved by matching the numeric UID and GID stored in the inode against /etc/passwd and /etc/group. Then come the size in bytes (0), the last modification time (Nov 2 18:10, known as mtime), and the filename (test.txt).

Showing hidden files with ls -la

ls hides any file whose name starts with a dot, such as .bashrc or .ssh. Every directory also contains two hidden entries, . (the current directory) and .. (the parent). Run ls -la to see all of them along with their permission masks.

ls -la Command for showing hidden files
ls -la Command for showing hidden files

How to move around with the cd command

With pwd to orient you and ls to inspect, cd (change directory) handles movement. Linux keeps all storage under a single tree that starts at the root directory (/), laid out by the Filesystem Hierarchy Standard (FHS). There are no drive letters like C: or D:. Secondary disks are mounted onto subdirectories of /.

Run cd / and the shell calls chdir("/"), which puts you at the top of the tree. Run cd /etc and you land in the directory that holds system-wide configuration. The prompt updates as you go, from thecybersecguru@thecybersecguru:~$ to thecybersecguru@thecybersecguru:/etc$.

Absolute vs relative paths

Both / and /etc are absolute paths. They begin with a slash and resolve to the same place wherever you currently stand. Relative paths have no leading slash and start from your current working directory. If you are in /etc and want /etc/apt, type cd apt.

cd shortcuts: .., -, and no argument

cd .. takes you one level up toward root. cd - jumps back to the last directory you visited by reading the shell’s $OLDPWD variable. cd with no arguments reads $HOME and returns you to /home/thecybersecguru.

Navigating the File System via cd Command

The cd, ls, pwd loop in practice

Reading about path resolution does not build the muscle memory you need during a live outage. In day-to-day administration you will run cd, ls, and pwd as a tight verification loop hundreds of times a day: move to a directory, list its contents to see how a service is laid out, and print your working directory before any command that modifies or deletes files. Try it:

thecybersecguru@thecybersecguru:~$ cd /etc
thecybersecguru@thecybersecguru:/etc$ ls
adduser.conf group- locale.gen os-release shells
alternatives hostname localtime pam.conf skel
apparmor hosts logrotate.conf pam.d ssh
apt init.d lsb-release passwd ssl
bash.bashrc inputrc machine-id profile sudoers
...
thecybersecguru@thecybersecguru:/etc$ pwd
/etc

Even this short listing shows how an Ubuntu machine is organized. hostname defines the server’s network identity, fstab (further down the list) controls which disks mount at boot, ssh holds the OpenSSH daemon configuration, and apt governs package repositories.

Running pwd at the end looks redundant when the prompt already says /etc$. It stops being redundant once you write commands with relative paths or wildcards, such as rm -rf ./temp/*. Make the loop a habit and you will not delete things in /etc while believing your terminal is still in /tmp.

How to get help in the Linux terminal

Memorizing fifty flags for twenty commands wastes effort. Experienced engineers look things up constantly, and they do it without leaving the terminal. Blog posts go stale. Production servers often sit in private subnets or air-gapped VLANs with no outbound internet. A flag documented online for a macOS/BSD utility, or for a newer Ubuntu release, may not exist on the Debian or Ubuntu LTS box in front of you. The documentation installed on the machine always matches the binaries on disk, and it comes in two tiers: quick syntax summaries with --help, and full reference manuals with man.

Quick syntax with –help and less

When you know the command and just need to recall a flag, pass --help, as in ls --help. Nearly all GNU coreutils programs parse it with the getopt_long() C library function. When the binary sees the flag, it skips its normal logic, writes a structured summary of its syntax and options to standard output (stdout, file descriptor 1), and exits with status 0.

On a real terminal this causes a problem. GNU ls has so many flags that the help text floods the screen in milliseconds, and you end up looking at the copyright footer while the options at the top have scrolled away. Scrolling with a mouse fails on a physical server console (TTY) or inside a multiplexer like tmux. The Unix answer is to pipe the output into a pager called less:

thecybersecguru@thecybersecguru:/etc$ ls --help | less

Understanding what the vertical bar does will change how you use Linux. When Bash parses ls --help | less, it asks the kernel for an anonymous in-memory buffer (the pipe() system call) and forks two child processes at once. The standard output (FD 1) of ls is wired to the write end of the buffer, and the standard input (FD 0) of less is wired to the read end. The help text never goes straight to your screen. less reads it from the pipe and paints one screenful at a time.

Inside less, the Up and Down arrows (or k and j) move one line at a time. Spacebar jumps a screen forward and b jumps back. Type / followed by a search term to search forward; for example, /-l and Enter highlights the -l option (use a long listing format). Press q to quit and return to your prompt.

Accessing Help Page of a Command

Full manuals with the man command

--help is a terse dictionary of flags. It rarely explains edge cases, which environment variables change a program’s output, or what its exit codes mean. For that, Unix-like systems provide man, short for manual.

When you run man ls, the program searches the standard documentation directories (mainly /usr/share/man) and finds a gzip-compressed file named /usr/share/man/man1/ls.1.gz. It decompresses the file on the fly, runs the groff/troff typesetting macros through the formatter to fit your terminal’s column width, and opens the result in your pager. On Ubuntu that pager is less, so the same arrow keys, / search, and q to quit all work.

Man page sections explained

Look at the top line of the screen when man ls opens. It reads LS(1). The 1 is not a version number. It is the manual section. Traditional Unix documentation is split into numbered sections so that commands, system calls, and config files with the same name do not collide. The ones you will meet most often are:

  • Section 1: executable programs and shell commands, such as ls(1) and touch(1).
  • Section 2: system calls provided by the Linux kernel, such as chdir(2) and stat(2).
  • Section 3: library calls from libraries like glibc, such as printf(3).
  • Section 4: special files, usually device nodes in /dev, such as null(4) and tty(4).
  • Section 5: file formats and configuration syntax, such as /etc/passwd, documented in passwd(5).
  • Section 6: games and screensavers.
  • Section 7: miscellaneous overviews, macro packages, and conventions, such as hier(7), which explains the Linux filesystem tree.
  • Section 8: system administration commands, typically for root, such as mount(8) and iptables(8).

Sections save you from a classic beginner headache. passwd is both the command that changes your password (Section 1) and the /etc/passwd file that stores user accounts (Section 5). man passwd opens Section 1 because it is the lowest numbered match. To read about the file format, give the section explicitly with man 5 passwd. If you forget how man itself works, run man man.

Overview of man Command

How a man page is organized

Well-formed man pages share a layout, so you know where to look while troubleshooting.

  • NAME: the command or file name and a one-sentence summary. mandb indexes this line, which is what makes keyword searches with man -k work.
  • SYNOPSIS: the formal grammar for arguments. For ls it reads ls [OPTION]... [FILE].... Square brackets mean optional, and an ellipsis means you can repeat the item. So ls needs no options and no paths (it defaults to the current directory), but accepts any mix of flags and targets, as in ls -l -a /etc /var.
  • DESCRIPTION: every short flag (like -a, one hyphen, combinable into clusters like -la) and long flag (like --all, two hyphens, easier to read in scripts), plus environment variables such as LS_COLORS and TIME_STYLE.
  • EXIT STATUS: the codes returned to the shell. For ls, 0 is success, 1 is a minor problem such as permission denied on a subdirectory, and 2 is a serious error such as an invalid flag.

Why man cd fails: shell built-ins vs disk binaries

Once you are comfortable with man on ls, pwd, and touch, try man cd on Ubuntu Server. Instead of a manual page, you get an error:

thecybersecguru@thecybersecguru:~$ man cd
No manual entry for cd

cd --help behaves oddly too. Bash answers with a terse usage line (bash: cd: --: invalid option, then cd: usage: cd [-L|[-P [-e]] [-@]] [dir]) instead of the long formatted output you got from ls --help.

The issues with man and --help commands
The issues with man and –help commands

Why does a command this basic have no manual page, and why does its help behave differently?

The answer sits at the boundary between the shell and the kernel. Linux commands fall into two groups: external executables stored as files on disk, and routines compiled into Bash itself, called shell built-ins. On modern Ubuntu releases, which use the usrmerge layout where /bin is a symlink to /usr/bin, ls and touch are standalone ELF (Executable and Linkable Format) binaries at /usr/bin/ls and /usr/bin/touch. When you type ls, Bash searches the colon-separated directories in your $PATH, finds /usr/bin/ls, calls fork() to spawn a child process, and uses execve() to replace that child’s memory image with the ls program. It prints the directory contents and exits.

Now imagine cd were an external binary at /usr/bin/cd. Every process has its own working directory pointer in the kernel, and a child inherits a copy of its parent’s directory at fork(). A child cannot change its parent’s working directory. If you ran cd /etc, Bash would fork a child, the child would call chdir("/etc") on itself and exit, and your shell would still be sitting in /home/thecybersecguru. For cd to move your session, the chdir() call has to run inside the Bash process itself. That is why cd is a shell built-in.

Using type -a to identify a command

You can ask Bash what any command really is before you run it. The type -a built-in prints every matching definition across aliases, functions, built-ins, and $PATH binaries:

thecybersecguru@thecybersecguru:~$ type -a ls
ls is aliased to `ls --color=auto'
ls is /usr/bin/ls
ls is /bin/ls
thecybersecguru@thecybersecguru:~$ type -a pwd
pwd is a shell builtin
pwd is /usr/bin/pwd
pwd is /bin/pwd
thecybersecguru@thecybersecguru:~$ type -a cd
cd is a shell builtin
Using type -a to identify a command
Using type -a to identify a command

Three things show up here. First, ls is wrapped in an alias (ls --color=auto) that your default .bashrc defines so directories and executables print in color. Behind it sits the real ELF binary at /usr/bin/ls, also reachable through the symlink /bin/ls.

Second, pwd is both a built-in and an external binary. Bash includes the built-in for speed, since it avoids forking a process, and so it can track your logical symlink path in $PWD. The standalone /usr/bin/pwd exists so that programs with no shell around, such as find -exec or C programs calling exec(), can still run it.

Third, cd is only a built-in.

Reading built-in documentation with help

Because cd belongs to Bash instead of a package in /usr/bin, its documentation lives in Bash’s own help system (and in the very long man bash page). When type says a command is a shell built-in, read its documentation with the help built-in, and pipe it into less just as you would --help:

thecybersecguru@thecybersecguru:~$ help cd | less
cd Command Help Page
cd Command Help Page

help cd gives the full specification for how Bash resolves directories, including the -L (logical symlink) and -P (physical inode) flags, how the CDPATH variable works, and which exit statuses cd returns when a directory change fails.

Linux navigation commands cheat sheet

CommandTypeWhat it doesExample and key behavior
pwdShell built-in and /usr/bin/pwd binaryPrints the absolute path of the current working directorypwd -P resolves all symlinks via getcwd() to show the physical path
lsAlias to /usr/bin/ls --color=autoReads directory entries and file inode metadata (stat)ls -la lists all files, including dotfiles, with permissions and mtime
touch/usr/bin/touch binaryCreates an empty file (openat) or updates timestamps (utimensat)touch test.txt checks write permission and creates a zero-byte file
cdShell built-in (chdir inside Bash)Changes the shell process’s working directorycd /etc jumps to /etc; cd - toggles back to $OLDPWD
cmd --help | lessGNU flag, kernel pipe, /usr/bin/lessSends the --help output to a scrollable pagerls --help | less: scroll with arrows, search with /, quit with q
man [section] name/usr/bin/man formatting /usr/share/manRenders standard Unix manual pages in lessman ls opens the Section 1 page; man 5 passwd opens the file format page
type -a / helpShell built-insIdentifies how a command is implemented and prints built-in docstype -a cd confirms it is a built-in; help cd prints Bash’s manual for it

What to learn next

With pwd, ls -la, and cd, you can walk any directory tree on a Linux server and read the ownership, permissions, and link structure of every file you meet. When you hit an unfamiliar command or a confusing error, type -a tells you whether it is a binary or a built-in, --help | less gives you the flags, and man and help give you the full specification.

The next part of this series covers the Bash shell itself, the layer between your keyboard and the kernel. It explains how environment variables like $PATH and $PS1 work, how startup files (.bashrc versus .profile) configure an SSH login session, and how the standard streams (stdin, stdout, and stderr) let you chain small utilities into pipelines.

Before that, compare the output of type -a pwd, help pwd, and man pwd to see how Bash’s built-in documentation differs from the standalone GNU coreutils page. If you find a useful flag in man ls, such as -h for human-readable sizes or -i for raw inode numbers, share your favorite flag combination in the comments.

Buy me A Coffee!

Support The CyberSec Guru’s Mission

🔐 Fuel the cybersecurity crusade by buying me a coffee! Your contribution powers free tutorials, hands-on labs, and security resources.

Why your support matters:
  • Writeup Access: Get complete writeup access within 12 hours
  • Zero paywalls: Keep the main content 100% free for learners worldwide

Perks for one-time supporters:
☕️ $5: Shoutout in Buy Me a Coffee
🛡️ $8: Fast-track Access to Live Webinars
💻 $10: Vote on future tutorial topics + exclusive AMA access

“Your coffee keeps the servers running and the knowledge flowing in our fight against cybercrime.”☕ Support My Work

Buy Me a Coffee Button

If you like this post, then please share it:

Linux

Discover more from The CyberSec Guru

Subscribe to get the latest posts sent to your email!

Related Posts

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.