Navigation#
Commands for moving around the tree, listing what’s in it, and
operating on the entries the operator finds. The shell tracks
$PWD and $OLDPWD for the operator; cd, pushd, and
popd are the levers that change them. Path traversal walks each
component in turn, so the x bit on every intermediate directory
is what actually controls where the operator can go.
On objective the operator lands in someone else’s tree. The first
job is orientation. Where am I, what is here, what was touched
recently, and what is the fastest path to the artifact I want.
On home turf the same verbs run for housekeeping. Both jobs share
cd, ls, find, and grep.
Filesystem navigation is a small set of verbs the operator chains together. The shell tracks state, the kernel walks paths, and the tools provide search and manipulation.
Stage |
Role |
|---|---|
Move |
Change |
List |
Enumerate the entries at a level. |
Inspect |
Read metadata (mode, size, type, hash). |
Operate |
Create, copy, move, or remove entries. |
Find |
Locate paths by name, type, size, or time. |
Grep |
Search inside file contents. |
Change Directories#
cd, pushd, and popd move $PWD; $OLDPWD holds the
previous directory. The -L flag keeps the logical path
(symlinks preserved); -P resolves them. -L is the default.
Command |
Effect |
|---|---|
|
Print the working directory ( |
|
Logical (default) / physical (resolves symlinks) |
|
Change directory |
|
Jump to |
|
Jump back to |
|
One / two levels up |
|
Jump to another user’s home (read from |
|
Resolve symlinks while changing dir |
|
Stop option parsing; for paths starting with |
|
Push current dir on the stack, then |
|
Rotate the stack from the left / from the right |
|
Pop the stack and |
|
Drop entry at +N / -N without |
|
List the directory stack with indices |
|
Clear the stack |
$ pwd
$ cd /etc && pwd && cd -
$ pushd /var/log >/dev/null
$ pushd /tmp >/dev/null
$ dirs -v
$ popd >/dev/null
List Directories#
Command |
Effect |
|---|---|
|
Sorted listing, no hidden files |
|
Include hidden; |
|
Long listing (mode, owner, size, mtime) |
|
Human-readable sizes |
|
Sorted by mtime, oldest first |
|
Sorted by size, largest first |
|
Recursive |
|
Only directories at this level |
|
Colored output |
|
Recursive tree view (separate package) |
|
Limit depth |
|
Ignore patterns |
|
Modern |
|
Another colored |
$ ls -lhA
$ ls -lhS /var/log | head
$ ls -d /etc/*/
$ tree -L 2 /etc/ssh
Create / Remove Directories#
Command |
Effect |
|---|---|
|
Create a directory |
|
Create parents as needed (no error if existing) |
|
Create with an explicit mode |
|
Remove an empty directory |
|
Remove if empty, plus newly-empty parents |
|
Recursive remove (non-empty) |
|
The foot-gun; verify the path twice |
|
Prompt once for recursive deletes (safer |
$ mkdir -p project/{src,test,docs}
$ mkdir -m 0750 secret/
$ rmdir empty/
$ rm -rI build/
Move / Rename Directories#
Command |
Effect |
|---|---|
|
Move or rename a directory |
|
Prompt before / never overwrite |
|
Treat NEW as a normal target (don’t “move into”) |
|
Recursive copy |
|
Archive copy (preserves perms, links, mtimes) |
|
CoW reflink recursive copy where supported |
|
Mirror; preferred for large or remote trees |
|
Mirror with progress; delete extras at DST |
$ mv old-name/ new-name/
$ cp -a /etc/ssh/ /tmp/ssh.bak/
$ rsync -aP --delete src/ /mnt/backup/src/
Create Files#
Command |
Effect |
|---|---|
|
Create empty file or bump mtime |
|
Update only atime / only mtime |
|
Set mtime to a specific date |
|
Create or truncate to zero bytes (one syscall) |
|
Same (only when |
|
Copy |
|
Create with explicit mode (and owner) |
|
Create a unique temp file in |
|
Create a unique temp directory |
$ touch placeholder.txt
$ : > log.txt
$ tmp=$(mktemp /tmp/work.XXXXXX)
$ tmpd=$(mktemp -d /tmp/work.XXXXXX)
$ sudo install -m 0600 /dev/null /etc/myapp.conf
Creating a multi-line file.
$ cat > file.txt <<EOF
> This is the first line
> This is the second line
> This is the third line
> EOF
Remove Files#
Command |
Effect |
|---|---|
|
Remove a file |
|
Prompt before each delete |
|
Never prompt; ignore missing |
|
Stop option parsing; for filenames starting with |
|
Single-file POSIX remove (no globbing, one arg) |
|
Overwrite then unlink (limited on CoW / journaled FS) |
|
Delete matches in one walk |
$ rm -i *.tmp
$ rm -- -dash-prefixed-file
$ shred -u secret.key
$ find /var/log -name '*.log' -mtime +30 -delete
Move / Rename Files#
Command |
Effect |
|---|---|
|
Move or rename |
|
Prompt before / never overwrite |
|
Move many into DIR (target first; safer in scripts) |
|
Copy a file |
|
Archive copy (preserves perms, links, mtimes) |
|
CoW reflink (Btrfs / XFS / APFS) |
|
Hard link (same inode) |
|
Symbolic link (path string) |
|
Batch rename via Perl regex (Debian, Ubuntu) |
$ mv draft.md final.md
$ mv -t /tmp a.txt b.txt c.txt
$ cp --reflink=auto big.iso big.iso.copy
$ ln -s /usr/bin/python3 ~/bin/python
$ rename 's/\.JPEG$/.jpg/' *.JPEG
Compress Files#
Quick reference. The Archives page covers the full table of formats, ratios, and pipelines.
Command |
Effect |
|---|---|
|
|
|
Keep the original |
|
|
|
|
|
|
|
Archive + gzip |
|
Archive + xz |
|
Archive + zstd |
|
Extract (modern tar auto-detects compressor) |
$ tar -czf logs.tgz /var/log
$ tar --zstd -cf src.tar.zst src/
$ tar -xf release.tar.zst -C /opt
$ zgrep -h ERROR /var/log/syslog.*.gz | head
Inspect Files#
Command |
Effect |
|---|---|
|
Full metadata (size, mode, owner, a/m/c times) |
|
Detect type from contents (ELF, JPEG, …) |
|
With MIME type |
|
Line, word, byte counts |
|
Size on disk, human-readable |
|
Cryptographic hash |
|
BLAKE3 (fast modern hash) |
|
Compare two files byte-by-byte |
|
Show line-level differences |
|
Who has this file open |
|
All files / sockets PID has open |
|
All open files anywhere under DIR |
|
PIDs using FILE (verbose) |
|
Kill processes blocking an unmount |
$ stat /etc/passwd
$ file -i unknown.bin
$ sha256sum *.iso > SHA256SUMS
$ diff -u config.yml config.yml.bak | less
$ sudo lsof /var/log/syslog
$ sudo lsof +D /mnt/usb
Edit Files#
Command |
Effect |
|---|---|
|
Modal editors (POSIX |
|
Beginner-friendly editor |
|
Emacs (TUI with |
|
Read-only |
|
POSIX line editors |
|
In-place substitution (GNU) |
|
BSD / macOS in-place (note empty arg) |
|
Portable in-place |
|
POSIX-correct in-place edit |
$ sudo nano /etc/hosts
$ sed -i.bak 's/foo/bar/g' config.yml
$ perl -pi -e 's/\r$//' file.txt
Search Files#
Find files by name, type, size, or time. find is POSIX and
walks the tree on every call; locate consults a pre-built index
(updatedb); fd is the modern fast replacement; fzf and
sk are interactive fuzzy filters that read paths from stdin.
Command |
Effect |
|---|---|
|
By filename glob |
|
Case-insensitive |
|
Restrict to regular files (or |
|
By size |
|
Modified in the last 7 days |
|
Newer than a reference file |
|
Delete matches |
|
Run cmd once per file |
|
Batch cmd invocations (faster) |
|
NUL-delimited piping (handles spaces) |
|
Pre-indexed search ( |
|
Where a command resolves on |
|
Binary, source, man page |
|
Shell built-in vs alias vs external |
|
Portable |
|
Friendlier |
|
Restrict by extension |
|
Files only, include hidden |
|
Interactive fuzzy filter (reads paths on stdin) |
|
Pick a file interactively |
|
Fuzzy find with file preview |
|
ripgrep-listed files into fzf |
|
Rust fuzzy finder; same idea as |
|
Go fuzzy filter; pipe-friendly |
|
fzf shell bindings, file picker / history search |
|
Frecency-ranked |
$ find /var/log -type f -name '*.log' -mtime -1
$ fd -e py main
$ fd . | fzf --preview 'bat {}'
$ command -v python3
$ sudo updatedb && locate sshd_config
Search Content#
Search inside file contents. grep is POSIX and everywhere;
rg (ripgrep) is the modern fast default and respects
.gitignore. Pipe results into fzf for an interactive picker.
Command |
Effect |
|---|---|
|
Print matching lines |
|
Recursive search |
|
Recursive with line numbers |
|
Case-insensitive |
|
Whole-word match |
|
Invert match (lines NOT matching) |
|
Count matching lines |
|
Just the filenames that match |
|
Files that do NOT match |
|
Extended regex (alternation, |
|
Perl-compatible regex (GNU) |
|
Fixed string, no regex |
|
3 lines of context after each match |
|
Context before / before+after |
|
Restrict by glob |
|
Skip directories |
|
NUL-delimited records (binary safe) |
|
Ripgrep (recursive, gitignore-aware) |
|
Restrict to a file type (Python here) |
|
Case-insensitive, two lines of context |
|
Filenames only |
|
List files ripgrep would search |
|
Silver searcher (similar to |
|
Perl-based, programmer-oriented |
|
Match lines via awk |
|
POSIX line search |
|
Binary search a sorted file |
|
Search printable strings in a binary |
|
Interactive jump-to-match picker |
|
Search compressed files in place |
$ grep -rn 'TODO' src/
$ grep -rn --include='*.py' --exclude-dir=.venv 'def main' .
$ rg -t py 'def main'
$ rg -i -C 2 'connection refused' /var/log/
$ zgrep -h ERROR /var/log/syslog.*.gz | head
Disk Usage#
Command |
Effect |
|---|---|
|
Free space per mounted filesystem |
|
With filesystem-type column |
|
Inode usage |
|
Total size of a directory |
|
Per-child sizes |
|
Largest entries under the current dir |
|
Interactive disk-usage TUI (third-party) |
|
Modern |
$ df -hT
$ du -sh /var/log /var/lib/docker
$ du -ah . | sort -rh | head -n 10
$ sudo ncdu /
Common Tasks#
The day-to-day filesystem verbs run as one-liners. List, copy, move, remove, make a directory, stat, count usage, find. These are the recipes the operator reaches for in any session, regardless of distribution or filesystem type.
List the current directory in long form.
$ ls -lah
Mirror a tree, preserving metadata.
$ cp -a src/ dst/
Move or rename in place.
$ mv old new
Recursive remove (verify the path twice).
$ rm -rf path/
Create a nested directory tree in one call.
$ mkdir -p a/b/c
Read full metadata for a single entry.
$ stat file
Total size of a directory.
$ du -sh dir
Free space per mounted filesystem.
$ df -h
Find and delete old logs in one walk.
$ find . -name '*.log' -mtime +7 -delete
References#
man 1 cd,man 1 pushd,man 1 popd,man 1 dirs(shell builtins for movement).man 1 ls,man 1 tree,man 1 stat,man 1 file(listing and inspection).man 1 cp,man 1 mv,man 1 rm,man 1 mkdir,man 1 rmdir,man 1 ln(basic file operations).man 1 find,man 1 locate,man 8 updatedb,man 1 xargs(path search).man 1 grep,man 1 sed,man 1 awk(content search).man 1 du,man 1 df,man 1 lsof,man 1 fuser(usage and open files).man 1 tar,man 1 gzip,man 1 zstd,man 1 xz,man 1 bzip2(compression).man 1 rsync,man 1 install,man 1 mktemp,man 1 shred(transfer and creation).Permissions for the
xbit on directories controlling path traversal.Files for the file model the navigation verbs operate on.
FHS for the standard tree the operator walks.
Archives for the full compression and archive reference.
Linux for the per-letter Linux command reference.