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!
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.

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.

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.txtthecybersecguru@thecybersecguru:~$ ls -ltotal 0-rw-rw-r-- 1 thecybersecguru thecybersecguru 0 Nov 3 18:20 test.txt

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.

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.
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 /etcthecybersecguru@thecybersecguru:/etc$ lsadduser.conf group- locale.gen os-release shellsalternatives hostname localtime pam.conf skelapparmor hosts logrotate.conf pam.d sshapt init.d lsb-release passwd sslbash.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.
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)andtouch(1). - Section 2: system calls provided by the Linux kernel, such as
chdir(2)andstat(2). - Section 3: library calls from libraries like glibc, such as
printf(3). - Section 4: special files, usually device nodes in
/dev, such asnull(4)andtty(4). - Section 5: file formats and configuration syntax, such as
/etc/passwd, documented inpasswd(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)andiptables(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.
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.
mandbindexes this line, which is what makes keyword searches withman -kwork. - SYNOPSIS: the formal grammar for arguments. For
lsit readsls [OPTION]... [FILE].... Square brackets mean optional, and an ellipsis means you can repeat the item. Solsneeds no options and no paths (it defaults to the current directory), but accepts any mix of flags and targets, as inls -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 asLS_COLORSandTIME_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 cdNo 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.

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 lsls is aliased to `ls --color=auto'ls is /usr/bin/lsls is /bin/lsthecybersecguru@thecybersecguru:~$ type -a pwdpwd is a shell builtinpwd is /usr/bin/pwdpwd is /bin/pwdthecybersecguru@thecybersecguru:~$ type -a cdcd is a shell builtin

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

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
| Command | Type | What it does | Example and key behavior |
|---|---|---|---|
pwd | Shell built-in and /usr/bin/pwd binary | Prints the absolute path of the current working directory | pwd -P resolves all symlinks via getcwd() to show the physical path |
ls | Alias to /usr/bin/ls --color=auto | Reads directory entries and file inode metadata (stat) | ls -la lists all files, including dotfiles, with permissions and mtime |
touch | /usr/bin/touch binary | Creates an empty file (openat) or updates timestamps (utimensat) | touch test.txt checks write permission and creates a zero-byte file |
cd | Shell built-in (chdir inside Bash) | Changes the shell process’s working directory | cd /etc jumps to /etc; cd - toggles back to $OLDPWD |
cmd --help | less | GNU flag, kernel pipe, /usr/bin/less | Sends the --help output to a scrollable pager | ls --help | less: scroll with arrows, search with /, quit with q |
man [section] name | /usr/bin/man formatting /usr/share/man | Renders standard Unix manual pages in less | man ls opens the Section 1 page; man 5 passwd opens the file format page |
type -a / help | Shell built-ins | Identifies how a command is implemented and prints built-in docs | type -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.









