Learn › Linux Foundations › Navigation

Chapter 2. Navigation: ls, cd, paths and tree

Final test: Chapter 2, Navigation. Twenty-five objectives on a real Debian 12 server: ls in ten forms, cd in ten forms with absolute and relative paths, and tree in five. Fifty minutes, graded from the commands you run and where you stand.

Chapter 2. Navigation

This chapter covers the following topics:

What you already know: Chapter 1 defined the terminal, the shell and the prompt, and you ran pwd. This chapter is about the directories pwd reports: seeing what is in them and moving between them.

Objectives

After this chapter you can:

The practice terminals in this chapter simulate the server admin@server1. Each one checks the single command it asks for, and nothing you type in them can break anything. When you start the practice machine from the panel, the real server takes their place. The graded lab at the end runs on a real Debian 12 server, prepares the chapter environment when you launch it. Follow the startup progress on screen. It records practice with the commands you run. On the real server ONE shell carries across every step of this chapter, so you stand wherever your last command left you. Every step below names where you should be standing. For a named location under your home directory, such as website, you can use ~/website from anywhere. Do not put ~/ in front of an absolute path or a move such as ..; those have their own meanings. If you are lost, type cd with nothing after it to return home, then pwd to confirm where you stand.

Pre-check 1 of 5: the working directory

Five questions before the material. A wrong answer costs nothing: the explanation states the fact and names the section that teaches it.

Pre-check 2 of 5: hidden entries

Pre-check 3 of 5: paths

Pre-check 4 of 5: cd with nothing after it

Pre-check 5 of 5: tree

2.1 The working directory

A directory is what other systems call a folder: a named container for files and for other directories. Every Linux system is one tree of directories that starts at a single root, written /.

Your shell is always standing in one directory, the working directory. When you run a command and name a file or directory without saying where it is, the command looks in the working directory. pwd, from Chapter 1, prints it, and it answers for wherever you are standing right now:

prompt: admin@server1:~$ answer: pwd output: /home/admin hint: Section 2.1. Three letters, no options: the command that prints the working directory. It answers from any directory.

The answer here is /home/admin, your home directory: the one directory on the machine that belongs to your account. The prompt writes it as ~. If your own shell printed something else, type cd with nothing after it and press Enter to return home, because every exercise below starts from there unless it says otherwise.

On this server it holds the working files of a small organization's web server: website, logs, data, backups, docs, scripts and archive. The file README.txt there describes each one. Nothing on this machine is permanent, because it is rebuilt from scratch on every launch.

2.2 Listing a directory: ls

ls lists the names inside a directory. Give it a path and it lists that directory; give it nothing and it lists the working directory. You are standing in your home directory. The path here is relative: website means the website directory inside where you stand, which is ~/website. From any other directory the same place is written ~/website.

Read the command as what to do, then where to do it. In ls website, ls lists names and website is the directory to inspect. A space separates the command from its argument. Running ls alone lists the current directory. Listing does not move you into another directory.

prompt: admin@server1:~$ answer: ls website ||| ls website/ ||| ls ~/website ||| ls ~/website/ output: README.md assets current index.html robots.txt about.html contact.html deploy.sh releases hint: Section 2.2. The listing command, then the path website, or ~/website from anywhere.

Nine names, arranged in columns to fit the window. This server sorts listings by byte value, which puts every capital letter before every lowercase one, so README.md comes first. A machine set to another language can order the same names differently.

Nothing here says which names are directories and which are files. Section 2.4 adds that.

2.2 Names with spaces

You are in your home directory. List data, the directory that holds the sales files, or ~/data from anywhere else:

prompt: admin@server1:~$ answer: ls data ||| ls data/ ||| ls ~/data ||| ls ~/data/ output: customers.csv inventory.csv orders.csv 'sales report.csv' hint: Section 2.2. The listing command, then the path data, or ~/data from anywhere.

One name came back in single quotes: sales report.csv. ls quotes any name that contains a space, so you can see where the name ends. The space is part of the name, and Section 2.6 shows what it costs when you type such a name yourself.

2.3 Hidden entries: ls -a

A file or directory whose name begins with a dot is a hidden entry. ls leaves hidden entries out unless asked. The convention exists so that the configuration files programs keep in your home directory do not appear in every listing. Nothing else is special about them.

An option, also called a flag, is a hyphen and a letter written after the command name to change what it does. The -a option, all, includes the hidden entries. You are in your home directory; the target is website, or ~/website from anywhere else:

Worked command: ls -a website. Read it in three pieces: list (ls), include hidden names (-a), in this directory (website). The option begins with one hyphen; the directory name does not.

prompt: admin@server1:~$ answer: ls -a website ||| ls -a website/ ||| ls -a ~/website ||| ls website -a output: . .git about.html contact.html deploy.sh releases .. README.md assets current index.html robots.txt hint: Section 2.3. The listing command with the option -a, then the path website, or ~/website from anywhere.

Three new names. .git is a hidden directory the version-control tool git keeps its records in. . and .. appear in every directory on Linux: . is the directory itself and .. is its parent, the directory that contains it. Section 2.6 uses .. to move up.

2.4 The long listing: ls -l

The -l option, long, prints one entry per line with its details. You are in your home directory; the target is docs, or ~/docs from anywhere else:

Worked command: ls -l docs. The lowercase letter l requests details; it is not the digit 1. Owner, group and permission fields describe access. Recognizing these columns is a separate skill from changing them with chown, chgrp or chmod.

prompt: admin@server1:~$ answer: ls -l docs ||| ls -l docs/ ||| ls -l ~/docs ||| ls docs -l output: total 16 drwxr-xr-x 2 admin admin 4096 Jan 15 2026 'meeting notes' -rw-r--r-- 1 admin admin 317 Jan 15 2026 onboarding.md -rw-r--r-- 1 admin admin 368 Jan 15 2026 runbook.md -rw-r--r-- 1 admin admin 145 Jan 15 2026 style-guide.md hint: Section 2.4. The listing command with the option -l, then the path docs, or ~/docs from anywhere.

Read one line left to right. The first character is the type: d for a directory, - for an ordinary file. A third type appears in the next listing.

The next nine characters are the permissions: who may read, write and run the entry. This chapter only asks you to recognize them on the line.

Then comes the link count, the number of directory entries that point at this thing. For a file it is the number of names it has, and a later step in this section shows a file with two. For a directory the count is 2 plus the number of directories inside it, because a directory is named by its parent, by its own ., and by the .. of every child.

The rest of the line is the owner, the group, the size in bytes, the date the contents were last modified, and the name.

total 16 is the disk space these four entries occupy, counted in blocks of 1024 bytes.

2.4 Combining options: ls -la

Options combine. -la is -l and -a together, in either order. You are still in your home directory; the target is website, or ~/website from anywhere else:

prompt: admin@server1:~$ answer: ls -la website ||| ls -al website ||| ls -l -a website ||| ls -la website/ ||| ls -la ~/website ||| ls -al ~/website output: total 44 drwxr-xr-x 5 admin admin 4096 Jan 15 2026 . drwxr-xr-x 10 admin admin 4096 Sep 6 21:03 .. drwxr-xr-x 2 admin admin 4096 Jan 15 2026 .git -rw-r--r-- 1 admin admin 178 Jan 15 2026 README.md -rw-r--r-- 1 admin admin 286 Jan 15 2026 about.html drwxr-xr-x 5 admin admin 4096 Jan 15 2026 assets -rw-r--r-- 1 admin admin 293 Jan 15 2026 contact.html lrwxrwxrwx 1 admin admin 19 Jan 15 2026 current -> releases/2026-08-01 -rwxr-xr-x 1 admin admin 275 Jan 15 2026 deploy.sh -rw-r--r-- 1 admin admin 396 Jan 15 2026 index.html drwxr-xr-x 5 admin admin 4096 Jan 15 2026 releases -rw-r--r-- 1 admin admin 68 Jan 15 2026 robots.txt hint: Section 2.4. The listing command with -la, the long option and the all option in one word, then website, or ~/website from anywhere.

Two lines deserve a look. current -> releases/2026-08-01 starts with l: it is a symbolic link, a name that points at another path, here the newest release. The arrow shows where it points.

The .. line carries a different date from every other line. Here .. is your home directory, and files are written into it while you work, so its date moves. Your date on that line will differ from the one printed above. Every other date reads Jan 15 2026, when these files were last modified.

Count the link column on the directories. website shows 5: the entry in its parent, its own ., and the .. inside .git, assets and releases.

2.4 Human-readable sizes: ls -lh

Sizes in bytes are exact and hard to read. -h, human-readable, prints them in K, M and G. You are in your home directory; the target is logs, or ~/logs from anywhere else:

prompt: admin@server1:~$ answer: ls -lh logs ||| ls -hl logs ||| ls -l -h logs ||| ls -lh logs/ ||| ls -lh ~/logs output: total 1.1M -rw-r--r-- 1 admin admin 773K Jan 15 2026 access.log -rw-r--r-- 1 admin admin 49K Jan 15 2026 auth.log -rw-r--r-- 1 admin admin 17K Jan 15 2026 cron.log -rw-r--r-- 1 admin admin 188K Jan 15 2026 error.log hint: Section 2.4. The listing command with -lh, long plus human-readable, then logs, or ~/logs from anywhere.

Compare with the plain long listing, ls -l logs, where the same files read in bytes:

total 1036
-rw-r--r-- 1 admin admin 791424 Jan 15  2026 access.log
-rw-r--r-- 1 admin admin  49980 Jan 15  2026 auth.log
-rw-r--r-- 1 admin admin  17000 Jan 15  2026 cron.log
-rw-r--r-- 1 admin admin 192090 Jan 15  2026 error.log

791424 bytes is 773K. K here is 1024 bytes, M is 1024K, so the rounded figure is what you say aloud and the byte count is what you compute with.

2.4 Largest first: ls -lS

A listing is sorted by name unless you ask otherwise. -S, a capital S, sorts by size, largest first. You are in your home directory, and the target is again logs, or ~/logs from anywhere else:

prompt: admin@server1:~$ answer: ls -lS logs ||| ls -Sl logs ||| ls -l -S logs ||| ls -lS logs/ ||| ls -lS ~/logs output: total 1036 -rw-r--r-- 1 admin admin 791424 Jan 15 2026 access.log -rw-r--r-- 1 admin admin 192090 Jan 15 2026 error.log -rw-r--r-- 1 admin admin 49980 Jan 15 2026 auth.log -rw-r--r-- 1 admin admin 17000 Jan 15 2026 cron.log hint: Section 2.4. The listing command with -lS, long plus the capital S that sorts by size, then logs, or ~/logs from anywhere.

access.log first, cron.log last. When a file system is full, ls -lS names the biggest files in a directory in one command. Options are case-sensitive: -s in lowercase prints the size in blocks instead of sorting.

2.4 Into every subdirectory: ls -R

-R, recursive, lists a directory, then every directory inside it, then every directory inside those. Recursive means the command repeats itself on whatever it finds. You are in your home directory. List website and every subdirectory beneath it, or ~/website from anywhere else:

prompt: admin@server1:~$ answer: ls -R website ||| ls -R website/ ||| ls -R ~/website ||| ls website -R output: website: README.md assets current index.html robots.txt about.html contact.html deploy.sh releases

website/assets: css img js

website/assets/css: site.css

website/assets/img: logo.svg

website/assets/js: app.js

website/releases: 2026-06-01 2026-07-15 2026-08-01

website/releases/2026-06-01: VERSION

website/releases/2026-07-15: VERSION

website/releases/2026-08-01: VERSION assets index.html

website/releases/2026-08-01/assets: css img js

website/releases/2026-08-01/assets/css: site.css

website/releases/2026-08-01/assets/img: logo.svg

website/releases/2026-08-01/assets/js: app.js hint: Section 2.4. The listing command with the capital option -R, then website, or ~/website from anywhere.

Each block is one directory, named on its own line with a colon, followed by its contents. .git does not appear: -R without -a skips hidden entries at every level. Section 2.7 shows the same facts drawn as a picture.

2.4 Marking the type: ls -F

-F, classify, appends one character to each name that says what it is: / for a directory, @ for a symbolic link, * for a file that can be run as a program. Ordinary files get nothing. You are in your home directory; the target is website, or ~/website from anywhere else:

prompt: admin@server1:~$ answer: ls -F website ||| ls -F website/ ||| ls -F ~/website ||| ls website -F output: README.md assets/ current@ index.html robots.txt about.html contact.html deploy.sh* releases/ hint: Section 2.4. The listing command with the capital option -F, then website, or ~/website from anywhere.

Two directories, one link, one program, five ordinary files. Now the backups directory:

2.4 A link that points at nothing

A symbolic link is only a name and a path. Nothing checks that the path still leads anywhere. You are in your home directory, and backups holds one such link. Mark the types in it, or in ~/backups from anywhere else:

prompt: admin@server1:~$ answer: ls -F backups ||| ls -F backups/ ||| ls -F ~/backups ||| ls backups -F output: db-2026-08-01.sql.gz latest@ site-2026-08-01.tar.gz hint: Section 2.4. The same capital -F option, then backups, or ~/backups from anywhere.

latest@ is a symbolic link. The long form, ls -l backups, shows where it points:

total 8
-rw-r--r-- 1 admin admin  142 Jan 15  2026 db-2026-08-01.sql.gz
lrwxrwxrwx 1 admin admin   34 Jan 15  2026 latest -> /mnt/backup/site-2026-09-01.tar.gz
-rw-r--r-- 1 admin admin 1989 Jan 15  2026 site-2026-08-01.tar.gz

It points at a file on a backup volume that is not mounted on this machine, so the target does not exist here. A link can outlive its target; this one is called a broken link, and the name still lists normally. Chapter 6 teaches how links are made.

2.4 Two names, one file: ls -i

Every file on a Linux file system carries an inode number, the identity the system uses in place of the name. Two names can carry one inode number, and then they are two names for one file. -i prints the number beside each name. You are in your home directory; the target is archive/2025, or ~/archive/2025 from anywhere else:

prompt: admin@server1:~$ answer: ls -i archive/2025 ||| ls -i archive/2025/ ||| ls -i ~/archive/2025 output: 131346 annual-report-final.txt 131294 q1 131296 q3 131346 annual-report.txt 131295 q2 131297 q4 hint: Section 2.4. The listing command with the option -i, then archive/2025, or ~/archive/2025 from anywhere.

Your numbers will differ, because a number is assigned when a file is created. What does not differ: annual-report.txt and annual-report-final.txt carry the SAME number, so they are one file. The long listing, ls -l archive/2025, shows the same fact in its second column, the link count of 2 on both names:

total 24
-rw-r--r-- 2 admin admin  166 Jan 15  2026 annual-report-final.txt
-rw-r--r-- 2 admin 

Practice Chapter 2. Navigation: ls, cd, paths and tree in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.