Why & When: find vs grep, and 'Everything Is a File'
- Choose find vs grep correctly every time: filesystem search vs content search
- Use grep -l to cross the bridge — search content but get back a filename
- Explain 'everything is a file' and read kernel state (/proc) and devices (/dev) with ordinary tools
- Answer 'what kind of file is this?' with file, stat, ls -l, and type
Doing vs. understanding
See why the mental model matters more than memorizing commands.
Most beginners collect commands like trading cards:
ls,cd,grep,find… and then freeze when a real task doesn't match a card they memorized. The people who are fast on Linux aren't the ones who memorized more — they carry a small set of mental models that tell them which tool the situation calls for.This lesson installs three of those models: find vs grep (the single most common mix-up), everything is a file (why the same handful of tools work everywhere), and what kind of file is this? (never trust a filename).
find vs grep: two verbs, never interchangeable
Reach for find when you want a file, grep when you want what's inside one.
Here is the whole distinction, and it never changes:
- `find` searches the _filesystem_ for files, by their name, type, size, age, owner, or permissions. It answers "where is the file?" It does not look inside files.
- `grep` searches _inside_ files for a line of text. It answers "what's in the file?" It does not hunt for filenames.
A quick self-check while typing: am I describing a filename pattern, or a word I expect to find in the content? Filename →
find. Content →grep.find /etc -name '*.conf'/etc/ssh/ssh_config.d/50-redhat.conf /etc/ld.so.conf /etc/rsyslog.conf /etc/logrotate.conf
- -name
- match the filename against a glob pattern (*.conf)
A find job: locate files by NAME anywhere under /etc. Grep literally cannot do this — it has no concept of 'files named .conf'. Quote '.conf' so the shell hands the pattern to find instead of expanding it first. Notice the word name is only one of find's powers. Because it searches the filesystem, it can match on any attribute the filesystem records — and that's what makes it far more than a filename lookup. Hunt for files by age, size, owner, or permissions and you're using find the way admins actually do:
find /var/log -name '*.log' -mtime -1 -size +1M/var/log/app.log /var/log/nginx/access.log
- -mtime -1
- modified less than 1 day (24h) ago (-1 = within, +1 = older than)
- -size +1M
- larger than 1 megabyte (+ = bigger than, - = smaller than)
Locate log files modified in the last day AND bigger than a megabyte — a real 'what filled up my disk overnight?' query. grep can't express any of this; none of it is about content, all of it is about the file's metadata. Stacked conditions like these are find's superpower. Example — not runnable on your lab box
grep CRITICAL /var/log/system.log2026-07-01 08:01:12 CRITICAL out of memory, killing worker 4 2026-07-01 08:05:31 CRITICAL replication lag exceeded threshold
A grep job: pull the lines that CONTAIN the word CRITICAL out of a file's contents. Find can't do this — it never opens the file. Same machine, opposite question. grep -rl 'debug = true' /etc --include='*.conf'/etc/myapp/app.conf
- -r
- recurse into a directory tree
- -l
- print the matching FILE's name, not the matching line
- --include
- only search files whose name matches this glob
The bridge between the two: grep -l searches CONTENT but reports the FILE that matched, not the line. -r recurses a directory tree; --include scopes it to real config files so a stray .txt saying the same thing doesn't sneak in. This is how you answer 'which file contains X?'. Check yourself
You need to locate every file named *.log under /var. Which tool?
Everything is a file
Understand why the same cat/stat/ls work on documents, kernel state, and devices alike.
Linux's defining idea: almost everything is presented as a file in the filesystem. Not just your documents, but:
- directories (a file that lists other files),
- devices — your disk, terminal, and
/dev/nullall appear under/dev, - live kernel state —
/procand/sysare virtual: reading them asks the kernel a question right now, - pipes and sockets used for inter-process communication.
Because they're all 'files', one small toolset reads them all —
cat,stat,ls,grep. You don't learn a new API per device; youcatit.cat /proc/loadavg0.14 0.09 0.06 1/213 2048
/proc/loadavg isn't a file on any disk — the kernel generates it the instant you read it. Yet plain cat works. That's 'everything is a file' in action: kernel state exposed through the filesystem. stat -c %F /dev/nullcharacter special file
- -c %F
- print just the human-readable file type
/dev/null is a device, not a document — stat reports its type as a 'character special file'. Same stat command you'd run on a text file; the metadata just says something different. Check yourself
Reading which top-level virtual directory shows you live kernel/process state as files?
What kind of file is this?
Identify a file's true type from content and metadata, never from its name.
A filename is just a label — Linux doesn't care about the
.txtor.shon the end.datacould be text, a JPEG, or a program. Four tools tell you what something really is:- `file` — sniffs the actual bytes and names the type ('ELF 64-bit executable', 'ASCII text', 'symbolic link').
- `stat` — the metadata: type, size, owner, timestamps.
- `ls -l` — its first character is the type flag:
-regular,ddirectory,lsymlink,cchar device,bblock device. It also shows a symlink's-> target. - `type` / `which` / `command -v` — for commands: is
lla real program, a shell builtin, or an alias?
file /bin/ls /etc/hostname /etc/rc0.d/bin/ls: ELF 64-bit LSB pie executable, x86-64 /etc/hostname: ASCII text /etc/rc0.d: symbolic link to ../rc.d/rc0.d
Three different real types, discovered by content — a compiled program, plain text, and a symlink — regardless of their names. This is why you 'ask the file what it is' instead of guessing from the extension. type -a lsls is aliased to `ls --color=auto' ls is /usr/bin/ls
- -a
- show ALL meanings (alias, builtin, and every binary on PATH)
For commands, type answers 'what will run when I type this?' Here ls is both an alias AND a real binary — the alias wins. which alone would only show the binary and miss the alias. Check yourself
A file named 'report.txt' — how do you check whether it's REALLY plain text and not, say, a disguised binary?
Now do it — put all three models to work in your live terminal
Run one command per model on your own machine so the distinctions become reflex.
Three tiny experiments, one per model. Do them in order — each one is the moment the idea stops being abstract. First, the find vs grep split: locate config files by name, then look inside config files for a word. Feel your brain pick the right verb each time.
find /etc -maxdepth 1 -name '*.conf'; echo '--- vs ---'; grep -rl 'path' /etc --include='*.conf' 2>/dev/null | headThe left half asks 'where are the .conf files?' (find, by name). The right half asks 'which .conf files mention path?' (grep -rl, by content). Same directory, two different questions — and you reached for a different tool for each without thinking. That's the model working. (Your terminal supplies the output.) cat /proc/loadavg; cat /proc/uptimeNow feel everything is a file: cattwo virtual files and watch the kernel answer with live numbers that exist nowhere on disk. Run them twice a few seconds apart — uptime's counter moves, proving you're reading the system right now, not a stored file.file $(which bash); file /etc/hostnameFinally, what kind of file is this? Ask fileabout a program and a text file back to back. One comes back 'ELF 64-bit executable', the other 'ASCII text' — types discovered from the bytes, not the names. You just used all three models in under a minute; string them together and no unfamiliar file or directory can intimidate you.
- find = search the filesystem for files (name/type/size/owner). grep = search inside files for text. If you're typing a filename pattern it's find; if you're typing a word to look for it's grep.
- grep -l (and grep -rl) bridges the two: it searches content but hands you back the matching file's name.
- Everything is a file — directories, devices (/dev), and live kernel state (/proc, /sys) all appear in the filesystem, so one toolset (cat/stat/ls/grep) reads them all.
- Never trust a filename: file sniffs content, stat/ls -l read metadata and the type character, and type/which resolve what a command actually is.
| The question you're asking | Reach for |
|---|---|
| Where is the file named X? | find -name |
| Which lines inside this file say X? | grep X file |
| Which file contains X? | grep -rl X dir/ |
| What type of thing is this? | file / stat / ls -l |
| What runs when I type this command? | type -a / command -v |
| What's the current kernel/process state? | cat /proc/... , /sys/... |
