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](https://i0.wp.com/thecybersecguru.com/wp-content/uploads/2026/11/20261103-0918-03.6048541.gif?resize=960%2C615&ssl=1)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: ``` <div>thecybersecguru@thecybersecguru:~<span class="tok-variableName tok-definition">$ pwd</span></div><div>/home/thecybersecguru</div> ``` 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](https://i0.wp.com/thecybersecguru.com/wp-content/uploads/2026/11/image-3.png?resize=960%2C117&ssl=1)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 → ](https://thecybersecguru.com/newsletter-subscription/) ### 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: ``` <div>thecybersecguru@thecybersecguru:~<span class="tok-variableName tok-definition">$ touch</span> test.txt</div><div>thecybersecguru@thecybersecguru:~<span class="tok-variableName tok-definition">$ ls</span> <span class="tok-propertyName">-l</span></div><div>total <span class="tok-number">0</span></div><div><span class="tok-propertyName">-rw-rw-r--</span> <span class="tok-number">1</span> thecybersecguru thecybersecguru <span class="tok-number">0</span> Nov <span class="tok-number">3</span> <span class="tok-number">18</span>:20 test.txt</div> ``` ![The ls -l Command Output](https://i0.wp.com/thecybersecguru.com/wp-content/uploads/2026/11/image-4.png?resize=878%2C146&ssl=1)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](https://i0.wp.com/thecybersecguru.com/wp-content/uploads/2026/11/image-5.png?resize=876%2C168&ssl=1)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: ``` <div>thecybersecguru@thecybersecguru:~<span class="tok-variableName tok-definition">$ cd</span> /etc</div><div>thecybersecguru@thecybersecguru:/etc<span class="tok-variableName tok-definition">$ ls</span></div><div>adduser.conf group- locale.gen os-release shells</div><div>alternatives hostname localtime pam.conf skel</div><div>apparmor hosts logrotate.conf pam.d <span class="tok-variableName">ssh</span></div><div>apt init.d lsb-release passwd ssl</div><div><span class="tok-variableName">bash</span>.bashrc inputrc machine-id profile sudoers</div><div>...</div><div>thecybersecguru@thecybersecguru:/etc<span class="tok-variableName tok-definition">$ pwd</span></div><div>/etc</div> ``` 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`: ``` <div>thecybersecguru@thecybersecguru:/etc$ ls --help | less</div> ``` 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: ``` <div>thecybersecguru@thecybersecguru:~$ man cd</div><div>No manual entry for cd</div> ``` `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](https://i0.wp.com/thecybersecguru.com/wp-content/uploads/2026/11/20261103-1333-19.4334175.gif?resize=960%2C615&ssl=1)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: ``` <div>thecybersecguru@thecybersecguru:~<span class="tok-variableName tok-definition">$ type</span> <span class="tok-propertyName">-a</span> <span class="tok-variableName">ls</span></div><div><span class="tok-variableName">ls</span> is aliased to `ls --color=auto<span class="tok-string">'</span></div><div><span class="tok-string">ls is /usr/bin/ls</span></div><div><span class="tok-string">ls is /bin/ls</span></div><div></div><div><span class="tok-string">thecybersecguru@thecybersecguru:~$ type -a pwd</span></div><div><span class="tok-string">pwd is a shell builtin</span></div><div><span class="tok-string">pwd is /usr/bin/pwd</span></div><div><span class="tok-string">pwd is /bin/pwd</span></div><div></div><div><span class="tok-string">thecybersecguru@thecybersecguru:~$ type -a cd</span></div><div><span class="tok-string">cd is a shell builtin</span></div> ``` ![Using type -a to identify a command](https://i0.wp.com/thecybersecguru.com/wp-content/uploads/2026/11/20261103-1341-14.3318611.gif?resize=960%2C614&ssl=1)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`: ``` <div>thecybersecguru@thecybersecguru:~<span class="tok-variableName tok-definition">$ help</span> <span class="tok-variableName">cd</span> | less</div> ``` ![cd Command Help Page](https://i0.wp.com/thecybersecguru.com/wp-content/uploads/2026/11/image-6.png?resize=960%2C614&ssl=1)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 | 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.