FHS and Finding Files - find, locate, and the FHS

FHS and Finding Files - find, locate, and the FHS

What You Will Achieve

  • Explain the purpose of the main directories in the FHS (Filesystem Hierarchy Standard)
  • Decide where files belong using the "shareable/unshareable" and "static/variable" classifications
  • Use the key find tests (-name / -type / -size / -mtime / -perm / -user / -newer / -exec) appropriately
  • Understand how locate / updatedb work and the role of /etc/updatedb.conf
  • Answer, with reasoning, when to use find vs locate, and which / whereis / type

This is the core of LPIC-1 objective 104.7 "Find system files and place files in the correct location". It is the skill of judging where config files and logs belong using the FHS, then actually locating them with find / locate.

Where Does Each File Belong in the FHS

FHS 3.0 is the specification that standardizes the Linux directory structure. Each directory has a clear role, and the type of file determines where it belongs. Start with the main directories that appear frequently on the exam.

Directory Purpose in the FHS
/bin Essential user command binaries (for all users)
/sbin System binaries
/etc Host-specific system configuration (static, unshareable)
/lib Essential shared libraries and kernel modules
/usr Shareable, read-only programs and data
/usr/bin Most user commands
/usr/sbin Non-essential system administration commands
/usr/local Software installed locally by the administrator
/var Variable data that changes during operation
/var/log Log files
/var/spool Spool data such as print and mail
/tmp Temporary files
/home Regular users' home directories
/root Home directory for the root user
/boot Static files of the boot loader and the kernel
/dev Device files
/proc Virtual filesystem of process and kernel information
/sys Virtual filesystem of device and kernel information
/opt Add-on application software packages
/mnt Mount point for a temporarily mounted filesystem
/media Mount point for removable media
/srv Data for services provided by this system

/bin and /sbin must hold "commands needed before /usr is mounted". Right after boot or in single-user mode, /usr may be a separate partition that is not yet mounted, so the minimal recovery commands are placed on the root partition by design.

/proc and /sys are virtual filesystems with no on-disk substance. /proc/cpuinfo and /sys/class/ are information the kernel generates dynamically; they are not a place to "save" files by editing.

What Are Shareable/Unshareable and Static/Variable

The FHS classifies files along two independent axes: "shareable vs unshareable" and "static vs variable". Once you understand this, why /usr and /var are separated finally clicks.

  • Shareable: files stored on one host and usable by other hosts (e.g., programs under /usr, /home)
  • Unshareable: files specific to that host (e.g., configuration in /etc, device lock files)
  • Static: files that do not change without administrator intervention (binaries, libraries, documentation)
  • Variable: files that normally change during operation (logs, spool, cache)
Shareable Unshareable
Static /usr, /opt /boot, /etc
Variable /var/mail, /var/spool/news /var/run, /var/lock

The point of this classification is to let you put static files on read-only media or apply a different backup policy to variable files only. Historically UNIX mixed both types, but consolidating variable files into /var allows /usr to be mounted read-only as a separate filesystem.

Choosing Between /usr and /usr/local

Software installed by the distribution's package manager goes in /usr (/usr/bin, etc.), while software the administrator installs manually goes in /usr/local (/usr/local/bin, etc.). The reason to separate the roles is clear, and not mixing them is the foundation of maintainable systems.

The /usr hierarchy is the package manager's (apt / dnf, etc.) territory and may be overwritten by OS upgrades or package updates. By contrast, /usr/local is untouched by package management, so putting software built from source or your own scripts there avoids accidents where an OS update deletes or conflicts with them.

Copying a self-built command directly into /usr/bin risks being overwritten or conflicting when a package of the same name is updated. The FHS intent is to place manual installs in /usr/local.

Using the Main find Tests

find walks a given directory in real time and locates files matching your conditions. Unlike locate, it always reflects the current state and can chain follow-up actions (deletion, permission change, etc.) in one go.

Step 1: Narrow by name and type

find /etc -name '*.conf' -type f
/etc/ssh/sshd_config.conf
/etc/logrotate.conf
/etc/resolv.conf

-name matches the filename (the base name at the end of the path) against a shell pattern. -type f means a regular file, -type d a directory, and -type l a symbolic link. Use -iname to ignore case.

Step 2: Search by size and modification time

find /var/log -type f -size +100M
find /home -type f -mtime -7
/var/log/journal/system.journal
/home/user/report-draft.md

-size +100M matches files larger than 100 MiB. The suffixes are c (bytes), k (KiB), M (MiB), G (GiB); + means "greater than" and - means "less than". -mtime -7 means "modified within 7 x 24 hours". Note that -mtime +1 means "modified at least 2 days ago" (fractional parts are discarded).

Step 3: Search by owner and permissions

find /home -user alice -perm -0200
find / -perm /4000 -type f 2>/dev/null
/home/alice/notes.txt
/usr/bin/passwd

-user alice matches files owned by alice. -perm /4000 means "any of the specified bits are set" (here SUID), while a - prefix such as -perm -0664 means "all of the specified bits are set". This is useful for auditing SUID bits.

Step 4: Batch-process the search results

find /tmp -name '*.tmp' -mtime +7 -exec rm {} +
find . -name '*.txt' -newer reference.txt -exec ls -l {} \;
-rw-r--r-- 1 user user 320 May 30 10:00 ./new-note.txt

-exec command {} \; runs the command once per matched file, with {} replaced by the filename. -exec command {} + appends multiple files to a single command line (similar to xargs), which is more efficient. -newer reference.txt selects files modified more recently than the reference file.

Escape the semicolon in -exec ... {} \; as \; (or ';') so the shell does not interpret it. Forgetting this causes errors such as find: missing argument to -exec.

How locate and updatedb Work

locate does not walk the filesystem directly; it searches a pre-built filename database, making it very fast. Many distributions use the mlocate implementation.

Step 1: Search quickly with locate

locate sshd_config
locate -i readme
/etc/ssh/sshd_config
/usr/share/doc/openssh-server/README

locate instantly returns names registered in the database. Use -i (--ignore-case) to ignore case. Note, however, that the results are a snapshot from "the last time the database was updated".

Step 2: Update the database with updatedb

sudo updatedb
locate newfile.txt
/home/user/newfile.txt

updatedb rebuilds the database. Newly created or deleted files are not reflected in locate results until you run updatedb. Many environments run it periodically via cron, but to find a file you just created, a manual update is needed.

Step 3: Tune the targets in /etc/updatedb.conf

grep -E 'PRUNEPATHS|PRUNEFS' /etc/updatedb.conf
PRUNEFS="NFS nfs nfs4 afs binfmt_misc ..."
PRUNEPATHS="/tmp /var/spool /media /var/lib/os-prober ..."

Tune the indexing targets in /etc/updatedb.conf. PRUNEPATHS lists directories to exclude from indexing, and PRUNEFS lists filesystem types to exclude. This prevents wasteful indexing of /tmp or network mounts.

When to Use find vs locate

Use find when you need real-time accuracy, and locate when you just want a fast name search. They do not compete; choose by use case.

find walks the disk so it is slow, but it is always current and supports rich conditions (size, modification time, permissions, owner) plus follow-up processing via -exec. locate reads the database so it is instant, but it is limited to name-based searches and does not reflect the current state until after updatedb. "Where is the file I just created" suits find; "what is the path of that config file" suits locate.

The Difference Between which / whereis / type

The three tools that look up a command's "location" have different purposes. Use which for the binary that gets executed, whereis for the full set of related files, and type for how the shell interprets a name.

which python3
whereis ls
type cd
type ll
/usr/bin/python3
ls: /usr/bin/ls /usr/share/man/man1/ls.1.gz
cd is a shell builtin
ll is aliased to `ls -alF'
  • which: returns the full path of the command executed from PATH
  • whereis: locates the binary, source, and manual page files of a command
  • type: a shell builtin; it indicates whether a name is interpreted as an alias, builtin, function, keyword, or file

A shell builtin like cd is not found by which (no executable file exists). "Why is which cd empty" is answered by type cd, which tells you it is a builtin.

Common Mistakes and Fixes

  • locate results are stale: a just-created file does not appear / a deleted file remains. Run sudo updatedb to refresh the database
  • Forgetting the semicolon for -exec: omitting \; in find ... -exec rm {} \; causes find: missing argument to -exec. Terminate with \; or +
  • Confusing /usr and /usr/local: putting self-built software in /usr/bin conflicts on package updates. Place manual installs in /usr/local
  • Misreading the sign of -mtime: mixing up -mtime -1 (within 24 hours) and -mtime +1 (at least 2 days ago). "Today's files" is -mtime -1
  • Looking up a shell builtin with which: which cd is empty and confusing. Use type to check builtins and aliases

Troubleshooting

Symptom: locate cannot find a just-created file

Cause: locate reads a database and only has a snapshot from when updatedb ran

Check:

locate newfile.txt

Fix: Run sudo updatedb to refresh the database, then search again. To reliably find the current state, use find.

Symptom: find -exec gives "missing argument to -exec"

Cause: The semicolon terminating the command is not escaped

Check:

find . -name '*.log' -exec ls -l {} \;

Fix: Always terminate the -exec command with \; (run one at a time) or + (run in batch).

Symptom: Running find / produces many permission errors

Cause: You are walking directories a regular user cannot read (parts of /proc or other users' areas)

Check:

find / -name target.conf 2>/dev/null

Fix: Discard standard error with 2>/dev/null, or narrow the scope to /etc etc. To reliably search the whole system, use sudo find.

Completion Checklist

  • [ ] Reviewed the purpose of the main FHS directories in a table
  • [ ] Understood the shareable/unshareable and static/variable classifications
  • [ ] Tried find searches by name, type, size, modification time, permissions, and owner
  • [ ] Confirmed the difference between -exec {} \; and -exec {} +
  • [ ] Reflected updates with sudo updatedb after a locate search
  • [ ] Used which / whereis / type appropriately

Summary

Goal Command / Location Point
Where config files go /etc (static, unshareable) Host-specific
Where variable data goes /var (logs, spool) Changes during operation
Manually installed software /usr/local Separated from package management
Conditional search + action find -size/-mtime/-exec Real-time, current, post-process
Fast name search locate + sudo updatedb DB lookup, needs update
Location of an executable which / whereis / type Choose by use case

The FHS is the map for judging the "correct location" of a file, while find / locate are the tools for finding the target file on that map. Master both, and you can trace configs and logs without getting lost even on an unfamiliar system.

Next Reading

Continue Your LPIC-1 Journey

LPIC-1 Hub

  • LPIC-1 Learning Hub — Full LPIC-1 article map, progress tracking, and exam objective coverage

Practice