Move Around the Filesystem
Problem statement
Move between folders with cd, check where you are with pwd, and list files with ls, including hidden ones. This is the first thing you do on any server: log in, find the app's folder, and look at its config and logs.
The script builds this small practice tree for you:
shop/
shop/├── config/│ ├── .env (hidden file)│ ├── ports.conf│ └── site.conf└── logs/ └── app.logDo these steps in order:
- Go into
shopand print where you are. - Go into
logsand print where you are. - Go back up one folder and print where you are.
- List the visible files in
config, one per line. - List all files in
config, including hidden ones, one per line.
Expected output:
Start: /shopIn logs: /shop/logsBack: /shopVisible files in config:ports.confsite.confAll files in config:.envports.confsite.confHints
/ is absolute (from the top of the tree). Any other path is relative (from the folder you are in now).Approach
Optimal: cd, pwd and ls
Covers: pwd, cd, ls -1, ls -A, ls -a, .., ., ~, absolute and relative paths.
The filesystem is one big tree. Windows has C:\, D:\ and so on. Linux has only one starting point, called the root, written as /. Every file and folder hangs somewhere below it. A few folders you will visit again and again on servers:
configs"]:::blue R --> VAR["/var"]:::gray R --> HOME["/home
users"]:::green R --> TMP["/tmp
scratch"]:::red VAR --> LOG["/var/log
logs"]:::yellow classDef blue fill:#dbeafe,stroke:#2563eb,color:#1e3a8a,stroke-width:2px classDef yellow fill:#fef3c7,stroke:#d97706,color:#78350f,stroke-width:2px classDef green fill:#d1fae5,stroke:#059669,color:#064e3b,stroke-width:2px classDef red fill:#fee2e2,stroke:#dc2626,color:#7f1d1d,stroke-width:2px classDef purple fill:#ede9fe,stroke:#7c3aed,color:#4c1d95,stroke-width:2px classDef gray fill:#f3f4f6,stroke:#6b7280,color:#111827,stroke-width:2px linkStyle default stroke:#94a3b8,stroke-width:2px
Where am I? Your shell always stands in one folder, called the working directory. pwd (print working directory) prints it. When you log in, you start in your home folder, for example /home/asha. The short name for your home folder is ~.
Two kinds of paths. An absolute path starts with / and works from anywhere, like /var/log/nginx. A relative path does not start with / and is read from where you stand. If you are in /var, then log/nginx means /var/log/nginx. Three short names help:
| Name | Means |
|---|---|
. |
this folder |
.. |
the folder one level up |
~ |
your home folder |
Moving with cd. cd folder (change directory) moves you. cd .. goes up one level. cd with nothing after it takes you home. cd - jumps back to the folder you were in before.
Looking with ls. ls lists what is in a folder. On its own it lists the current folder, or you can give it a folder name like ls config. Some useful flags:
| Flag | What it does |
|---|---|
-1 |
one name per line (good for scripts) |
-a |
show hidden files, plus . and .. |
-A |
show hidden files, but not . and .. |
-l |
long form: permissions, owner, size, date |
-h |
with -l, sizes like 4.0K instead of 4096 |
On a real server you will type ls -la all the time. It shows everything, with details. We do not use -l here, because its dates and owner names change on every machine.
Hidden files. Any name that starts with a dot, like .env or .bashrc, is hidden from a plain ls. This is just a habit of ls, not a security feature. Anyone who can read the folder can see them with -a. Config and secrets often live in dotfiles, so always check with ls -A when something seems missing.
Walking through the code. The # Setup: lines only create the sample files, so skip past them. They make the tree in a new temporary folder, so they never touch your real files.
cd "$base/shop"uses an absolute path, because$basestarts with/.cd logsis relative: it means "thelogsfolder inside where I am now".cd ..goes back up toshop.ls -1 configlists the visible files. The hidden.envis not shown.ls -1A configadds the hidden file.
The echo lines print ${PWD#"$base"} instead of the full path. $PWD holds the same path that pwd prints, and #"$base" cuts the random temporary part off the front. That trick only exists so the output looks the same on every machine. On a real server you just type pwd.
Edge cases. If a folder is empty, ls prints nothing and still succeeds. If a folder does not exist, cd and ls print an error and fail, so check the spelling. Linux names are case-sensitive: Logs and logs are two different folders.
# Setup: build a small practice tree in a fresh temporary folder
base=$(mktemp -d)
mkdir -p "$base/shop/config" "$base/shop/logs"
printf 'port=8080\n' > "$base/shop/config/ports.conf"
printf 'name=shop\n' > "$base/shop/config/site.conf"
printf 'SECRET=abc123\n' > "$base/shop/config/.env"
printf 'started\n' > "$base/shop/logs/app.log"
# ${PWD#"$base"} hides the random temp part, so the output is the same on every machine
cd "$base/shop" # absolute path: starts with /
echo "Start: ${PWD#"$base"}"
cd logs # relative path: from where we stand
echo "In logs: ${PWD#"$base"}"
cd .. # .. means "one folder up"
echo "Back: ${PWD#"$base"}"
echo "Visible files in config:"
ls -1 config # -1 = one name per line
echo "All files in config:"
ls -1A config # -A = also show hidden files (but not . and ..)Interview follow-ups
ls is missing or broken on the server. How do you list a folder?
The shell can list files by itself, without
ls.echo config/*prints every visible name inconfig, because the shell expands the*into the matching names. For hidden files, addconfig/.[!.]*, which matches names that start with one dot. For one name per line, useprintf '%s\n' config/* config/.[!.]*. You can also usefind config -maxdepth 1, which lists everything one level deep, hidden files included.
Frequently asked questions
Both show hidden files. -a also shows the two special entries . (this folder) and .. (the folder above), which every folder has. -A leaves those two out, so you only see real files. In scripts -A is usually what you want, because . and .. are never files you want to act on. At the terminal, ls -la is the common habit, and seeing . and .. does no harm.
A relative path depends on where the script was started. If someone runs your script from their home folder instead of the app folder, cd logs fails or, worse, goes to a different logs folder. Safe scripts either use absolute paths, like /var/log/myapp, or first move to a known place. A common line is cd "$(dirname "$0")", which moves to the folder the script itself lives in. Relative paths are fine when you are typing by hand and can see where you are.
/etc holds system and app configuration, like /etc/nginx/nginx.conf. /var/log holds logs, which is where most debugging starts. /home holds each user's folder, and /root is the admin's home. /tmp is for temporary files and is often emptied on reboot, so never keep anything important there. Apps you install yourself often go in /opt or /srv.