Learn › Linux Foundations › Search
find - a hands-on Linux lab on a real virtual machine.
Hunt through an archive with find filters: by name, case-blind name, type, size, age, and depth. Stack filters into precise one-line hunts, then prove it with three from-memory challenges in the practice terminal.
You have a folder called archive sitting in your home directory, and it is stuffed: reports, logs, images, config files, scripts, all nested in subfolders several levels deep. Somewhere in there is a single file you need. Opening folders one at a time with ls until you stumble across it could take all afternoon.
Linux has a command built for exactly this: find. You point it at a folder and describe what you are looking for, by name, by kind, by size, by age, and it walks the entire tree for you and prints every match. In this lesson you will hunt through archive half a dozen different ways.
find is one of the oldest tools you will meet, part of Unix since the mid 1970s at Bell Labs. Its age shows in its option style: whole words after a single dash, like -name and -size, a spelling that predates the flag conventions most newer commands use. Old, but nothing has replaced it in fifty years.
The black boxes below are a practice terminal: a safe sandbox that only checks the one command each step teaches, so you cannot break anything. On the real machine at the end of the module, the mission builds this same archive folder and installs the search tools, and you run these hunts for real.
One habit first. find prints its matches in filesystem order, which is not alphabetical and can differ from one machine to the next. To get a stable, readable list, you pipe the output through sort. A pipe is the | character: it feeds the output of the command on its left into the command on its right. So find ... | sort means "find the matches, then hand them to sort to put in order." Every hunt in this lesson ends in | sort for exactly that reason.
Before you search for one thing, look at everything. Give find just a folder and no other instructions, and it prints every single path underneath it. Pipe it through sort so the list comes out in order:
find ~/archive | sort
Before you run it, decide: will the list show only files, or folders too? And will the archive folder itself appear in its own list?
prompt: student@linuxcamp:~$ answer: find ~/archive | sort output: /home/student/archive /home/student/archive/backup /home/student/archive/backup/app.conf.bak /home/student/archive/backup/empty-dir /home/student/archive/config /home/student/archive/config/.secret.conf /home/student/archive/config/app.conf /home/student/archive/config/logging.conf /home/student/archive/images /home/student/archive/images/banner.png /home/student/archive/images/hero.jpg /home/student/archive/images/logo.png /home/student/archive/images/photo.jpg /home/student/archive/logs /home/student/archive/logs/access.log /home/student/archive/logs/auth.log /home/student/archive/logs/big.log /home/student/archive/logs/system.log /home/student/archive/reports /home/student/archive/reports/2024 /home/student/archive/reports/2024/annual.txt /home/student/archive/reports/2024/q1-summary.txt /home/student/archive/reports/2024/q2-summary.txt /home/student/archive/reports/2025 /home/student/archive/reports/2025/data.csv /home/student/archive/reports/2025/metrics.csv /home/student/archive/reports/2025/q1-summary.txt /home/student/archive/scripts /home/student/archive/scripts/backup.sh /home/student/archive/scripts/cleanup.sh /home/student/archive/scripts/deploy.sh hint: Type find, a space, the path ~/archive, then a space, the pipe character, a space, and sort. Like this: find ~/archive | sort
Both answers: folders AND files, and yes, the very first line is archive itself. That is the whole haystack: six top folders (backup, config, images, logs, reports, scripts) and everything nested inside them. Notice find printed the full address of each thing, every line starting with /home/student/archive, because you gave it the path ~/archive and the ~ is shorthand for your home directory. Next you start narrowing it down.
The most common hunt is by filename. The -name option tells find to keep only the paths whose final name matches a pattern you give it. The pattern uses * as a wildcard meaning "any run of characters," so '*.log' means "anything ending in .log." Wrap the pattern in single quotes so the shell hands the * to find untouched.
Find every log file in the archive:
find ~/archive -name '*.log' | sort
Before you run it, commit to a number: how many .log files do you remember seeing in the full haystack?
prompt: student@linuxcamp:~$ answer: find ~/archive -name '*.log' | sort output: /home/student/archive/logs/access.log /home/student/archive/logs/auth.log /home/student/archive/logs/big.log /home/student/archive/logs/system.log hint: Add -name and the quoted pattern after the path: find ~/archive -name '*.log' | sort
Four log files, pulled out of the whole tree by their .log ending. The pattern '*.log' matched the name at the very end of each path, no matter how deep it lived. Change the pattern and you change the hunt: '*.csv' would find the spreadsheets, and an exact name with no * at all finds files carrying exactly that name.
Here is a detail worth knowing. Run find ~/archive -name '*.conf' | sort and one of the matches is /home/student/archive/config/.secret.conf, a hidden file whose name starts with a dot. find matches hidden files just like any other. A plain shell wildcard typed at the prompt would skip dotfiles; find -name does not. That is one reason find is the tool you trust to catch everything.
-name is strict about capital letters: the pattern '*.PNG' and the filename logo.png do not match, because PNG and png are different strings to -name. When you do not know how a file was capitalized, swap in -iname, the case-insensitive twin. The i stands for "ignore case."
Hunt for PNG images using a deliberately wrong-case pattern:
find ~/archive -iname '*.PNG' | sort
Before you run it, decide: the archive's image names are all lowercase, so will this capital-letters pattern match them or come back empty?
prompt: student@linuxcamp:~$ answer: find ~/archive -iname '*.PNG' | sort output: /home/student/archive/images/banner.png /home/student/archive/images/logo.png hint: Same shape as -name but with -iname: find ~/archive -iname '*.PNG' | sort
It matched. -iname treated *.PNG and *.png as the same pattern, so both lowercase PNG files came back. With plain -name the exact same command would have printed nothing at all. When a hunt for a name you are sure exists comes back empty, wrong capitalization is one of the first things to suspect, and -iname is the one-letter fix.
Sometimes you want only files, or only folders. The -type option filters by kind. -type f keeps only regular files; -type d keeps only directories (Linux's word for folders). You can stack it with -name to say "a file, and its name matches this."
List only the directories in the archive:
find ~/archive -type d | sort
Before you run it, make a call: counting archive itself, how many directories does the whole tree hold?
prompt: student@linuxcamp:~$ answer: find ~/archive -type d | sort output: /home/student/archive /home/student/archive/backup /home/student/archive/backup/empty-dir /home/student/archive/config /home/student/archive/images /home/student/archive/logs /home/student/archive/reports /home/student/archive/reports/2024 /home/student/archive/reports/2025 /home/student/archive/scripts hint: Add -type d after the path to keep only directories: find ~/archive -type d | sort
Ten directories, and every file vanished. The archive's skeleton is now clear: six top folders plus reports splitting into 2024 and 2025, and a lone empty-dir tucked inside backup. Flip it to -type f and you would get the opposite, only the files. Combine it with a name pattern and you can narrow to "regular files ending in .sh", which you will do yourself in the challenges.
Pause here for a second, because you just crossed a line most beginners never notice. With three options, -name, -iname, and -type, you can already answer questions like "where is every config file?" without opening a single folder. The rest of this lesson adds size, age, and depth to that same sentence shape: find, a place, a filter.
You can hunt by how big a file is. The -size option takes a number and a unit. A leading + means "larger than," so -size +1M means "larger than 1 megabyte." This is how you track down the space hogs in a folder without opening a single one.
Find the files in the archive bigger than one megabyte:
find ~/archive -size +1M | sort
Before you run it, decide: out of the thirty-odd files in the archive, do you expect a handful of large ones or many?
prompt: student@linuxcamp:~$ answer: find ~/archive -size +1M | sort output: /home/student/archive/images/hero.jpg /home/student/archive/logs/big.log hint: Add -size +1M after the path (a capital M for megabytes): find ~/archive -size +1M | sort
Just two files clear the one-megabyte bar: a large image and a large log. Everything else in the archive is small enough that -size +1M skips it. You can go the other way too: a leading - means "smaller than," so -size -1M would list the small files instead. And filters stack: add a -name pattern before the size and you narrow to large files of one kind, another combination the challenges will ask of you.
Files also have an age: the time they were last changed. The -mtime option filters by that, counted in days. -mtime +7 means "last changed more than 7 days ago" (the old stuff); -mtime -7 means "changed within the last 7 days" (the fresh stuff). This is how you find stale files to clean up, or recent files to review.
The archive's reports folder has an older batch and a newer batch. Find the reports older than a week:
find ~/archive/reports -mtime +7 | sort
Before you run it, commit: which year's reports do you expect on the old side, 2024 or 2025?
prompt: student@linuxcamp:~$ answer: find ~/archive/reports -mtime +7 | sort output: /home/student/archive/reports/2024/annual.txt /home/student/archive/reports/2024/q1-summary.txt /home/student/archive/reports/2024/q2-summary.txt hint: Point find at ~/archive/reports and add -mtime +7 for older-than-7-days: find ~/archive/reports -mtime +7 | sort
The three files in the 2024 folder are the old ones, all last changed more than a week ago, so -mtime +7 catches them. Swap the sign to -mtime -7 and you get the fresh side: the three 2025 files, plus a small surprise, the reports, 2024, and 2025 directory entries themselves. A directory's own timestamp updates whenever something is added or removed inside it, and that happened when the archive was built, so the folders count as recently changed too. Think in relative buckets here, older-than or newer-than a number of days, rather than exact calendar dates. The actual dates depend on when the archive was built and will read differently on your machine.
One last filter, and it is about depth rather than the files themselves. By default find digs all the way down every branch. -maxdepth 1 tells it to stop one level down: the folder you named and its direct contents, nothing deeper. It is how you ask "what is at the top of this tree?" without the flood.
find ~/archive -maxdepth 1 | sort
Before you run it, decide: at depth one, will any actual files appear, or is the top level of this archive folders all the way across?
prompt: student@linuxcamp:~$ answer: find ~/archive -maxdepth 1 | sort output: /home/student/archive /home/student/archive/backup /home/student/archive/config /home/student/archive/images /home/student/archive/logs /home/student/archive/reports /home/student/archive/scripts hint: Add -maxdepth 1 right after the path: find ~/archive -maxdepth 1 | sort
Seven lines: the base folder plus its six direct children, and not a single file among them, because everything in this archive lives inside a subfolder. -maxdepth counts levels from the starting folder, so -maxdepth 2 would go one layer deeper, and so on. One quirk to remember: -maxdepth likes to come first, right after the path, before filters like -name. Put it after them and find will complain with a warning.
That completes your filter kit: name, case-blind name, type, size, age, depth. find can also DO something to each match with an option called -exec, and it has a faster database-driven cousin called locate. Each of those gets its own full lesson later in this module. First, prove the filters are yours.
Scaffolding off. No command is shown from here on.
A teammate swears there are two different files in the archive both named exactly q1-summary.txt, and wants proof. Hunt the whole ~/archive tree for that exact filename, sorted. Remember: an exact name is just a pattern with no wildcard in it.
prompt: student@linuxcamp:~$ answer: find ~/archive -name 'q1-summary.txt' | sort output: /home/student/archive/reports/2024/q1-summary.txt /home/student/archive/reports/2025/q1-summary.txt hint: Use -name with the exact filename in single quotes, no asterisk needed, then | sort
Two files, same name, different years. Your teammate was right, and you proved it in one line without opening a folder. An exact -name pattern matches only that precise spelling, which is exactly what a duplicate hunt needs.
Still no command shown. The archive contains shell scripts, files whose names end in .sh. List them, sorted, but be precise about it: ask for regular files only AND the matching name pattern, two filters stacked in one hunt.
prompt: student@linuxcamp:~$ answer: find ~/archive -type f -name '*.sh' | sort output: /home/student/archive/scripts/backup.sh /home/student/archive/scripts/cleanup.sh /home/student/archive/scripts/deploy.sh hint: Stack -type f and -name '*.sh' after the path, then | sort
Three scripts, and stacking the filters is the skill: find only kept paths that passed BOTH tests, a regular file and a .sh ending. Every filter you add is another AND. That is how one command turns a vague hunch into a precise question.
One more, from memory. Produce a sorted map of just the top level of the archive, and make it directories only. That means the base folder and its direct subfolders: anything past level one cut off, any files filtered out. Two filters again, one for depth, one for kind.
prompt: student@linuxcamp:~$ answer: find ~/archive -maxdepth 1 -type d | sort output: /home/student/archive /home/student/archive/backup /home/student/archive/config /home/student/archive/images /home/student/archive/logs /home/student/archive/reports /home/student/archive/scripts hint: Depth filter first (-maxdepth 1), then -type d, then | sort
The same seven lines as your plain depth-one hunt, and that repeat is itself the finding: adding -type d removed nothing, which proves every top-level entry in this archive is a directory. Sometimes what a filter does NOT remove is the answer. You just drove three hunts with zero prompting. The filters are yours.
You earned this cheat sheet. Every row is a hunt you just ran on the archive:
The one idea that ties it all together: find is a sentence. A place to search, then filters that stack as ANDs, each one narrowing the hunt. Later lessons in this module add the verbs: -exec to act on each match, and locate with updatedb for instant database lookups.
When a find command returns nothing, do not assume the file is gone. Loosen the hunt first: drop -type, widen the -name pattern to '*part*', try -iname in case the capitalization is off, or search a folder higher up. An empty result usually means the filter was too tight, not that the file is missing.
The practice terminal has walked you through every filter: the full tree, -name and its case-blind twin -iname, -type, -size, -mtime, and -maxdepth, plus three hunts you built entirely from memory.
The Search module ends with one real Linux machine: the search mission lab. There a VM boots just for you with this same archive filesystem and the search tools installed. The mission hands you objectives that use exactly what you just ran, and it shows no commands. You read the objective, recall the filter, and type it. That recall is what makes it stick.
Finish the other Search lessons, then go run the hunt for real.
Practice find in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.