find Command in Linux with Examples

Last updated Saturday, June 6, 2026 11:38 am Joshua James 9 min read

Large Linux filesystems rarely fail because files are impossible to locate; they fail because the search is too broad, too noisy, or too risky to act on. The find command in Linux gives you a controlled way to match paths by name, type, size, timestamps, permissions, and directory depth before you list, inspect, or clean anything.

Use find when shell globs are not enough, when filenames contain spaces, or when you need recursive checks under a specific path. The examples use GNU find from findutils, which is the normal implementation on Ubuntu, Fedora, Debian, RHEL-family, and many other full Linux installations.

Use the find Command Syntax

GNU find walks one or more starting directories and evaluates an expression against every path it visits. If you omit the starting path, it searches the current directory. If you omit the expression, it prints every matched path.

find [starting-point...] [expression]

The expression controls what find matches and what it does with each match. It can contain tests, actions, options, and operators:

  • Tests: Conditions such as -name, -type, -size, -mtime, and -perm decide whether a path matches.
  • Actions: Actions such as -print, -printf, -delete, and -exec decide what happens to matches.
  • Options: Options such as -maxdepth, -mindepth, -depth, -L, and -P change traversal behavior.
  • Operators: Operators such as -a, -o, !, and grouped parentheses combine tests. When no operator appears between tests, find treats it as AND.

The Linux find manual page documents the GNU syntax, while the GNU findutils expression reference is useful when you need deeper details about tests, actions, and operator precedence.

find Command Quick Reference

TaskCommand PatternWhat It Does
Search current directory onlyfind . -maxdepth 1 -type f -printLists regular files directly under the starting directory without walking subdirectories.
Find files by namefind . -type f -name '*.log' -printSearches below the current directory for regular files ending in .log.
Ignore filename casefind . -type f -iname '*report*' -printMatches names such as Report, report, and REPORT.
Match several extensionsfind . -type f \( -name '*.txt' -o -name '*.md' \) -printUses grouped OR logic so one search can match multiple filename patterns.
Find hidden pathsfind . -mindepth 1 -name '.*' -printMatches dotfiles and dot directories while avoiding the starting directory itself.
Limit recursion depthfind . -maxdepth 2 -type d -printLists directories no deeper than two levels below the starting point.
Find large filesfind . -type f -size +1G -printMatches regular files larger than 1 GiB.
Find recent filesfind . -type f -mmin -60 -printMatches files modified within the last 60 minutes.
Find older filesfind logs -type f -mtime +30 -printMatches files whose contents were modified more than 30 days ago.
Find executable filesfind . -type f -perm /u=x -printMatches files with the user execute bit set.
Find world-writable filesfind . -type f -perm -0002 -printMatches files that any user can write to.
Find broken symlinksfind -L . -type l -printFollows links, then prints symlinks whose targets cannot be resolved.
Skip subtreesfind . \( -path './cache' -o -path './logs' \) -prune -o -type f -printPrunes selected directories before continuing through the rest of the tree.
Handle unusual namesfind . -type f -print0Prints NUL-delimited names for safe use with xargs -0.
Preview cleanupfind tmp -type f -name '*.tmp' -printShows the exact matches before any deletion action runs.

Verify the find Command on Linux

Most full Linux installations already include find. Confirm the command path and implementation before relying on GNU-specific actions such as -printf:

command -v find
find --version | head -n 1

Example output from a GNU findutils system:

/usr/bin/find
find (GNU findutils) 4.10.0

If a minimal image does not include find, install the findutils package from the normal distro repositories. Avoid removing baseline utilities just to reproduce a missing-command error.

sudo apt install findutils        # Debian, Ubuntu, Linux Mint
sudo dnf install findutils        # Fedora, RHEL-family, CentOS Stream
sudo pacman -S findutils          # Arch Linux, Manjaro
sudo zypper install findutils     # openSUSE

Create a Safe Practice Tree for find Examples

The examples use a temporary directory under your home folder so searches, previews, and deletion tests stay away from real data. Keep the same terminal session open because the $demo variable stores the cleanup path.

demo=$(mktemp -d "$HOME/find-demo.XXXXXX")
mkdir -p "$demo"/{logs,docs,cache,tmp,scripts,src,empty-dir}

printf 'Root note\n' > "$demo/root-note.txt"
printf 'INFO start\nERROR timeout\n' > "$demo/logs/app.log"
for i in {1..200}; do printf 'large log line %03d\n' "$i"; done > "$demo/logs/big.log"
printf 'old log\n' > "$demo/logs/old.log"
printf 'cached=true\n' > "$demo/cache/generated.conf"
printf 'port=8080\n' > "$demo/src/app.conf"
chmod 0644 "$demo/src/app.conf"
printf 'Project notes\n' > "$demo/docs/readme.txt"
printf 'Quarterly results\n' > "$demo/docs/Quarterly Report.txt"
printf 'Markdown notes\n' > "$demo/docs/notes.md"
printf 'TOKEN=\n' > "$demo/docs/.env.sample"
: > "$demo/docs/empty.txt"
printf 'release marker\n' > "$demo/docs/release.marker"
printf 'New release notes\n' > "$demo/docs/newer-notes.txt"
printf '#!/bin/sh\nprintf "deploy\\n"\n' > "$demo/scripts/deploy.sh"
chmod +x "$demo/scripts/deploy.sh"
printf 'temporary\n' > "$demo/tmp/delete-me.tmp"
printf 'fresh\n' > "$demo/tmp/recent.dat"
printf 'public scratch\n' > "$demo/tmp/world-writable.txt"
chmod 666 "$demo/tmp/world-writable.txt"

touch -d '45 days ago' "$demo/logs/old.log"
touch -d '60 days ago' "$demo/docs/readme.txt" "$demo/docs/Quarterly Report.txt" "$demo/docs/notes.md" "$demo/docs/.env.sample" "$demo/docs/empty.txt"
touch -d '2 days ago' "$demo/docs/release.marker"
touch -d '1 day ago' "$demo/docs/newer-notes.txt"
ln -s docs/readme.txt "$demo/readme-link"
ln -s missing-target "$demo/broken-link"

cd "$demo"
printf 'Demo directory: %s\n' "$demo"

Every command that starts with find . assumes your shell is inside that demo directory.

Find Files by Name, Type, and Path

Find Files in the Current Directory Only

Use -maxdepth 1 when you want files in the starting directory but not in subdirectories. This avoids a common mistake where a quick check turns into a full recursive scan.

find . -maxdepth 1 -type f -print | sort
./root-note.txt

Find Files by Exact Name Pattern

Search for regular files whose names end in .log. Quote the pattern so your shell does not expand it before find sees it.

find . -type f -name '*.log' -print | sort
./logs/app.log
./logs/big.log
./logs/old.log

Find Files with Case-Insensitive Names

Use -iname when capitalization is inconsistent across files created by different users or applications.

find . -type f -iname '*report*' -print | sort
./docs/Quarterly Report.txt

Find Multiple File Extensions

Group -name tests with escaped parentheses when one search needs OR logic. The shell must pass the parentheses to find, so keep the backslashes.

find docs -type f \( -name '*.txt' -o -name '*.md' \) -print | sort
docs/empty.txt
docs/newer-notes.txt
docs/notes.md
docs/Quarterly Report.txt
docs/readme.txt

Find Hidden Files and Dotfiles

find does not skip hidden files by default, but a pattern such as .* can also match the starting directory. Add -mindepth 1 when the goal is hidden paths below the start point.

find . -mindepth 1 -name '.*' -print | sort
./docs/.env.sample

Find Directories at a Limited Depth

-maxdepth prevents a broad search from walking deeper than needed. This is useful before cleaning caches, scanning project roots, or checking only top-level service directories.

find . -maxdepth 2 -type d -print | sort
.
./cache
./docs
./empty-dir
./logs
./scripts
./src
./tmp

Skip One or More Directories with prune

Use -prune when a directory should not be searched at all. This first command skips ./cache, then prints matching config files elsewhere.

find . -path './cache' -prune -o -type f -name '*.conf' -print | sort
./src/app.conf

The cache directory contains generated.conf, but -prune removes that subtree from the search before the -name '*.conf' test runs on the remaining paths.

For multiple exclusions, group the path tests before -prune. Keep the final -print on the right side of -o so pruned directories do not appear as normal results.

find . \( -path './cache' -o -path './logs' \) -prune -o -type f -name '*.conf' -print | sort
./src/app.conf

Find Symbolic Links or Follow Them

By default, GNU find does not follow symbolic links. Use -type l to locate links themselves.

find . -type l -print | sort
./broken-link
./readme-link

Add -L before the starting point when the search should evaluate the linked target instead of the symlink object.

find -L . -type f -name 'readme-link' -print | sort
./readme-link

Find Broken Symbolic Links

A broken symlink points to a target that no longer exists. Add -L, then test for remaining link objects with -type l.

find -L . -type l -print | sort
./broken-link

Find Files by Size, Time, and Permissions

Find Files Larger Than a Size

Size tests use suffixes such as k, M, and G. A plus sign means larger than the size, while a minus sign means smaller than the size.

find . -type f -size +1k -print | sort
./logs/big.log

For disk-usage triage after you identify large paths, use the du disk usage analysis guide to compare directory totals and filesystem usage.

Find Files Between Two Sizes

Combine two -size tests when the useful range has both a lower and upper bound. The following search matches log files larger than 1 KiB but smaller than 10 KiB.

find logs -type f -size +1k -size -10k -print | sort
logs/big.log

Find Files Modified Recently

-mmin uses minutes instead of whole 24-hour periods. Refresh the demo timestamps first so the output does not depend on when you created the practice tree.

touch tmp/delete-me.tmp tmp/recent.dat tmp/world-writable.txt
find tmp -type f -mmin -60 -print | sort
tmp/delete-me.tmp
tmp/recent.dat
tmp/world-writable.txt

Find Files Older Than a Number of Days

-mtime +30 matches files whose content was modified more than 30 days ago. Search a narrow path first when old-file cleanup could remove data.

find logs -type f -mtime +30 -print | sort
logs/old.log

Find Files Newer Than a Marker File

-newer is useful after deployments, migrations, or backup runs because it compares paths to a known marker file.

find docs -type f -newer docs/release.marker -print | sort
docs/newer-notes.txt

Find Executable Files

The -perm /u=x test matches files where the owner execute bit is set. This is a quick way to audit scripts before changing modes recursively.

find . -type f -perm /u=x -print | sort
./scripts/deploy.sh

Use the chmod command guide before applying bulk permission changes, especially when executable bits, recursive modes, or symbolic permissions are involved.

Find Files with an Exact Permission Mode

An exact -perm mode matches files whose permission bits equal that mode. Use this for audits, not as proof that the owner or group is correct.

find src -type f -perm 0644 -print | sort
src/app.conf

Find World-Writable Files

-perm -0002 matches files where the other-write bit is set. That is often a security smell outside temporary scratch directories.

find . -type f -perm -0002 -print | sort
./tmp/world-writable.txt

Find Files Without a Valid Owner or Group

After deleting users, restoring backups, or moving data between systems, -nouser and -nogroup can reveal files whose numeric IDs no longer map to local accounts. Treat this as a diagnostic list before changing ownership.

sudo find / -xdev \( -nouser -o -nogroup \) -print 2>/dev/null

-xdev keeps the search on the starting filesystem, which avoids crossing into mounted drives, network shares, containers, or special filesystems during a broad system audit.

Find Empty Files

The -empty test matches empty regular files when paired with -type f. It also matches empty directories when paired with -type d.

find . -type f -empty -print | sort
./docs/empty.txt

Format and Pipe find Output Safely

Print Custom Fields with printf

GNU -printf lets you format output without sending each match to another command. The %p directive prints the path, while %s prints the file size in bytes.

find . -maxdepth 2 -type f -name '*.log' -printf '%p %s bytes\n' | sort
./logs/app.log 25 bytes
./logs/big.log 3800 bytes
./logs/old.log 8 bytes

The GNU findutils print-field reference lists the available directives when you need owners, modes, timestamps, or relative paths in reports.

Count Matches Without Printing Every Path

Counting lines from -print is fine for ordinary names, but -printf '.' avoids path text entirely and counts one marker per match.

find logs -type f -name '*.log' -printf '.' | wc -c
3

Search Matched Files for Text

find selects paths; grep searches file contents. Pair them when you need to search only a specific file set, such as configuration files under one directory.

find src -type f -name '*.conf' -exec grep -H 'port' {} +
src/app.conf:port=8080

Use the grep command guide for regular expressions, inverted matches, context lines, and recursive content searches that do not need find to preselect files. For matched-path workflows that need more than this simple handoff, use the find exec command guide for detailed -exec, -execdir, and confirmation examples.

Preserve Filenames with print0 and xargs

Whitespace breaks careless pipelines. Use -print0 with xargs -0 when matched names may contain spaces, tabs, quotes, or newlines.

find docs -type f -name '*Report*' -print0 | xargs -0 -n1 basename
Quarterly Report.txt

The GNU manual’s file deletion examples explain why NUL-delimited output matters for unusual filenames and why direct shell command substitution is a poor fit for arbitrary path lists.

Delete Matches Safely with find

Deletion is where find needs the most restraint. Preview the exact matches, narrow the starting path, and only then replace the preview action with -delete.

find tmp -type f -name '*.tmp' -print | sort
tmp/delete-me.tmp

-delete permanently removes matched paths. Run the preview from the same starting path and expression first, and do not use it under broad paths such as / or your full home directory unless you have reviewed the match set carefully.

find tmp -type f -name '*.tmp' -delete
find tmp -type f -name '*.tmp' -print | wc -l
0

The zero count confirms the temporary file no longer matches.

Delete Empty Directories Only

Empty-directory cleanup should target directories, not files. Preview with -type d and -empty, then run the same expression with -delete.

find . -depth -type d -empty -print | sort
./empty-dir
find . -depth -type d -empty -delete
find . -depth -type d -empty -print | wc -l
0

Use the rmdir command guide when directory-removal behavior, parent cleanup, or failed non-empty removals need more explanation.

Troubleshoot Common find Command Errors

find command not found

A stripped-down image may not include find, or $PATH may not include the directory that contains it. Check the shell lookup first:

command -v find

No output means the shell cannot find the command. Install findutils through the distro package manager, then verify the path and version again. For broader command-location checks, compare executable lookup behavior with the which command guide or inspect standard binary and manual paths with the whereis command guide.

find: paths must precede expression

This error often appears when the shell expands an unquoted wildcard before find receives it. For example, if the current directory contains both a.log and b.log, an unquoted *.log becomes two separate arguments.

touch a.log b.log
find . -name *.log -print
find: paths must precede expression: `b.log'
find: possible unquoted pattern after predicate `-name'?

Quote the pattern so find receives it as a pattern instead of a shell-expanded file list.

find . -name '*.log' -print

Remove the two throwaway files after testing the quoting error.

rm -f a.log b.log

find reports permission denied

Permission errors mean the starting path includes directories your current user cannot read. A root-owned path may print the directory name and then the failed child traversal.

LC_ALL=C find /root -maxdepth 1 -print
/root
find: '/root': Permission denied

Prefer a narrower path you own. Use sudo only when the task genuinely requires protected directories. If you only want to continue through readable paths while hiding permission noise, redirect standard error:

find /etc -name '*.conf' -print 2>/dev/null

find returns no matches

No output is not always an error. It usually means the starting path, filename case, file type, or time/size test does not match the files you expected.

pwd
find . -maxdepth 1 -print
find . -type f -iname '*log*' -print

Check your current directory first, then relax one condition at a time. Switch from -name to -iname when case might be different, and remove -type f temporarily when the match could be a directory or symbolic link.

find returns too many results

Overly broad output usually comes from starting too high in the filesystem or missing a type, depth, or path exclusion. Inspect a small preview before changing the expression.

find . -maxdepth 2 -type f -print | head -n 20

If the preview shows cache, dependency, or generated directories that should not be searched, add -prune exclusions and run another preview before using the result for cleanup or bulk processing.

find . \( -path './cache' -o -path './logs' \) -prune -o -type f -print | head -n 20

Argument list too long after command substitution

Shell command substitution such as rm $(find ...) breaks on large match sets and corrupts filenames with spaces or newlines. A common symptom is bash: /usr/bin/rm: Argument list too long.

Preview matches first, then use a find action that processes paths without expanding them through the shell.

find tmp -type f -name '*.tmp' -print
find tmp -type f -name '*.tmp' -delete
find tmp -type f -name '*.tmp' -print | wc -l
0

A zero count means the cleanup expression no longer matches anything under tmp.

For commands that need another tool, prefer -exec ... {} + or -print0 with xargs -0 instead of command substitution.

printf is not recognized

-printf is a GNU find feature. Minimal BusyBox-style environments may support common tests such as -name, -type, and -mtime but reject GNU-only formatting actions.

find --version | head -n 1

If the command does not identify GNU findutils, install the distro’s findutils package or replace -printf with a simpler portable action such as -print.

Clean Up the Practice Tree

Remove the temporary practice tree after you finish testing. The printf line prints the exact directory stored in $demo so you can confirm the target before deletion.

The cleanup command deletes the demo directory and everything inside it. Confirm that $demo points to the temporary find-demo. path created earlier before running rm -rf.

printf '%s\n' "$demo"
cd
rm -rf -- "$demo"

Conclusion

find is ready to turn recursive filesystem searches into reviewed match sets: names, extensions, hidden paths, sizes, timestamps, permissions, links, counts, and safe cleanup targets. Quote patterns, start from the narrowest useful path, preview destructive matches, and use -print0, -printf, or -exec when plain path output is not enough.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show more of our fresh Linux tutorials in Top Stories and From your sources when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Let us know you are human: