find Cheatsheet - Linux File Search Reference

locate answers from a prebuilt index and is fast but stale; find computes on every run and is slower but authoritative, and it is the only one that can filter by size, age or permission bits and then act on what it finds. The sheet spans six filter dimensions plus an actions group: -iname for case-insensitive matching, -type to separate directories from files and symlinks, -size +100M, -mtime -1, permission bitmasks, and ownership cleanup. The actions group is what find cannot be replaced for: -exec feeds matches one at a time, -exec ... + batches them to amortise process startup, and -delete removes them directly. The judgement calls matter more than the flags: find follows symlinks by default and imposes no depth limit, so on a large tree it needs -maxdepth and -prune to finish in reasonable time. Boolean ordering is the other trap, since expressions like -prune -o -print rely on short-circuit evaluation and print the wrong set when reordered. Run a plain -print pass before adding -delete; it is the only insurance that operation has.

SysOps·37 commands·Last updated 2026-07-21
findFile Searchlinux

Typical Use Case

When a live disk alert climbs to 90 percent but you are not sure which directory is growing, that is the most common use case for find. Start with du for the directory overview, then list files over 1G directly with find . -type f -size +1G, and use -mtime -3 to find files touched in the last three days — often an abnormal log or temp file. Once you find the culprit, pair -exec or -delete to clear stale .log/.tmp files in one pass, far more efficient than browsing directories on a full disk.

By Name 6

find . -name "file.txt"
Find files by name (supports wildcards)
find . -iname "file.txt"
Case-insensitive name search
find . -name "*.log"
Find all .log files
find . -name "file*"
Find files starting with 'file'
find /var/log -name "*.gz"
Search within a specific directory
find . -maxdepth 2 -name "*.log"
Limit search depth to 2 levels (-mindepth sets the minimum)

By Type 5

find . -type f
Find only regular files
find . -type d
Find only directories
find . -type l
Find only symlinks
find . -type f -name "*.sh"
Find .sh files
find . ! -type d
Exclude directories (find non-directories)

By Size 5

find . -size +100M
Find files larger than 100 MB
find . -size -1k
Find files smaller than 1 KB
find . -empty
Find empty files or directories
find . -size 0
Find files of size 0
find . -size +10M -size -100M
Find files between 10 MB and 100 MB

By Time 5

find . -mtime -7
Find files modified within the last 7 days
find . -mtime +30
Find files modified more than 30 days ago
find . -mmin -60
Find files modified within the last 60 minutes
find . -atime -1
Find files accessed within the last day
find . -newer file.txt
Find files newer than file.txt

By Permission 4

find . -perm 755
Find files whose permission is exactly 755
find . -perm -u+x
Find files where the owner has execute permission
find . -perm /o+w
Find files writable by others
find . -perm -g=w
Find files writable by the group

By Owner 5

find . -user tom
Find files owned by a specific user
find . -group dev
Find files owned by a specific group
find . -uid 1000
Find by UID
find . -nouser
Find files with no owner (user deleted)
find . -nogroup
Find files with no group

Actions 7

find . -name "*.tmp" -delete
Delete matched files
find . -name \"*.sh\" -exec chmod +x {} \;
Run a command on each matched file
find . -name \"*.log\" -exec rm {} +
Batch-run a command (more efficient)
find . -name "*.txt" -print
Print matched file paths
find . -name \"*.bak\" -ok rm {} \;
Confirm before each execution
find . -name node_modules -prune -o -name "*.js" -print
Exclude a directory then continue (-prune)
find . -type f -exec ls -lh {} + | sort -k5 -rh
Sort by file size

Parameter matrix

ParameterEffectExample
-name <pattern>Match on file name with shell wildcards; case sensitivefind . -name "*.log"
-iname <pattern>Same as -name but case insensitive, for directories holding mixed-case extensionsfind . -iname "file.txt"
-maxdepth N / -mindepth NBound the recursion depth so a large tree is not walked end to end for nothingfind . -maxdepth 2 -name "*.log"
-type f|d|lFilter by node type - regular file, directory, symlink - the precondition for any later actionfind . -type f
! -type dNegate to drop directories and emit everything else, symlinks includedfind . ! -type d
-size +100M / -size -1kFilter by size, plus for larger than and minus for smaller than, to pin down what fills the diskfind . -size +100M
-size +10M -size -100MStack two -size tests into a range, keeping only files between the two thresholdsfind . -size +10M -size -100M
-empty / -size 0Hit empty files and directories, or restrict the check to zero-byte filesfind . -empty
-mtime -N / -mtime +NSelect a modification-time window: minus means within the last N days, plus means older than N daysfind . -mtime -7
-mmin -NDrop the time granularity to minutes, for logs and configs that just changedfind . -mmin -60
-newer <reference>Use one file modification time as the baseline and return everything newerfind . -newer file.txt
-perm 755 / -perm -u+x / -perm /o+wThree permission forms - exact match, contains a bit, any-of - with clearly different meaningsfind . -perm /o+w
-user / -group / -uidFilter by ownership, to clean up output produced by one account or groupfind . -user tom
-nouser / -nogroupHit entries with no owner or no group, the signature of leftovers from deleted accountsfind . -nouser
-deleteDelete matches directly with no external command attached; it really changes the filesystemfind . -name "*.tmp" -delete
-exec <cmd> {} \;Start one command per match, which copes with paths containing spaces and newlinesfind . -name "*.sh" -exec chmod +x {} \;
-exec <cmd> {} +Batch every match into a single invocation, far cheaper in process overheadfind . -name "*.log" -exec rm {} +
-ok <cmd> {} \;Ask for confirmation per match, the only built-in guard before a bulk actionfind . -name "*.bak" -ok rm {} \;
-prunePrune an entire subtree such as node_modules and keep matching the restfind . -name node_modules -prune -o -name "*.js" -print
-printPrint matches only as a read-only dry run, then swap in the delete action once verifiedfind . -name "*.txt" -print

Common pitfalls

SymptomAfter the delete some files are still there, or directory contents that should have been kept got wiped.

Cause-exec and -delete modify the filesystem during the walk, so an over-broad pattern removes files with no way back.

FixSwap the action out first, run a read-only combination such as find . -name "*.txt" -print to list the hits, check them one by one, then put -delete back.

SymptomOn a large tree the command prints nothing for a long time and looks hung.

Causefind recurses from the start point to every leaf and reads each directory on the way down, which gets expensive purely by directory count; nothing is wrong with the disk.

FixShrink the scope with find . -maxdepth 2 -name "*.log", prune directories you do not need, then widen the conditions gradually.

SymptomThe same file appears in one run and is missing from the next.

CauseThe tree keeps changing while find walks it - an application writing logs, a build writing artifacts - so find is reading a directory tree in motion.

FixNarrow the scope to a concrete directory with find . -maxdepth 2 -name "*.log", or wait for writes to stop; do not take a full count during a heavy write period.

SymptomRunning -exec one match at a time on a big tree takes minutes.

CauseThe per-match form starts a process for every hit, so with tens of thousands of matches the spawn and scheduling cost dwarfs the work the command actually does.

FixUse the batch form find . -name "*.log" -exec rm {} + to hand every path to a single invocation.

SymptomThe target clearly exists, yet find reports no such file or directory.

CauseWhen a pattern contains spaces or wildcards and is left unquoted, the shell expands it first into names in the current directory, so find never receives the original pattern.

FixQuote the pattern, as in find . -name "*.log", and make sure the relative form matches the walk start point.

SymptomAfter cleaning up with -empty the directory structure collapsed and the toolchain stopped starting.

Cause-empty matches empty files and empty directories alike, so removing empty build directories breaks anything that relies on that layout.

FixRestrict the sweep to regular files, for example find . -type f -empty -delete, which touches files only.

SymptomThe goal was to exclude node_modules and the whole result set came back empty.

CauseWhen -prune evaluates true it drops the whole branch; if it is not separated with -o it also swallows the matches that should have continued.

FixJoin the two sides with -o as in find . -name node_modules -prune -o -name "*.js" -print and confirm no grouping was rewritten around them.

SymptomThe permission count is off by an order of magnitude from what was expected.

Cause-perm 755 demands an exact match, so a single setuid bit or a different group field excludes the file, while -perm -u+x and -perm /o+w are contains and any-of tests with a far larger hit set.

FixDecide which relation you mean: exact with find . -perm 755, contains with find . -perm -u+x, or a loose sweep with find . -perm /o+w.

SymptomThe report mixes files and directories and looks like it double-counts.

CauseA search without -type returns directories too, and find . -type f and find . -type d walk the same paths, so merging the outputs without deduplicating repeats rows.

FixState the type explicitly, or keep non-directories only with find . ! -type d, and check for overlap when merging the two lists.

SymptomThe search for recently modified files returns nothing.

CauseThe sign on a time test is easy to invert: -mtime -3 is within the last three days while -mtime +3 is older than three days, so a flipped sign lands the window in an empty range.

FixValidate the direction with find . -mtime -7 first, confirm there is output, then move to an older cut such as -mtime +30.

Troubleshooting

  1. 1Narrow the scope first and confirm depth plus filters behave as expected

    find . -maxdepth 2 -name "*.log"

    With -maxdepth the output must stay within two levels; empty means nothing matches at this depth, too much means the filter needs to get stricter.

  2. 2Rank by size to find what actually fills the disk

    find . -type f -exec ls -lh {} + | sort -k5 -rh

    The top lines after the reverse sort are the largest files; if this is slow, bound the walk with -maxdepth first.

  3. 3Keep only the files inside one size band

    find . -size +10M -size -100M

    Two stacked -size tests form the range; an empty result means nothing lives in that band, not that the command is wrong.

  4. 4Skip the heavy directory and keep matching the rest

    find . -name node_modules -prune -o -name "*.js" -print

    The matched node_modules and everything under it stay out of the output while the other .js files remain, which shows the -o join is correct.

  5. 5Sweep for world-writable files as a security check

    find . -perm /o+w

    Any output means a file is writable by others; review each one to confirm it is a deliberately shared directory such as a cache.

  6. 6Hunt leftovers whose owning account no longer exists

    find . -nouser

    The listed paths have no matching user, meaning the owner is gone from the system; reassign ownership or clean them up.

  7. 7Check permission bits with the symbolic form instead of an exact number

    find . -perm -u+x

    This hits every file the user can execute; if the count looks far off, compare against find . -perm 755 for the exact-755 subset.

Command Examples

List files larger than 1GB below the current directory

find . -type f -size +1G

-size +1G matches regular files larger than 1G. Drop -type f and large directories join the list as well, which is rarely what you want.

Output

./backup/dump.sql
./media/concert_4k.mp4

Find config files modified in the last 3 days

find /etc -type f -mtime -3

-mtime -3 covers anything modified within the last three days, =3 means exactly three days ago and +3 means older than three days. The sign decides the direction, and getting it backwards is the classic slip.

Output

/etc/nginx/nginx.conf
/etc/hosts

Delete log files older than 30 days

find /var/log -name "*.log" -mtime +30 -delete

-delete really deletes and prints nothing. Run the same search without it to confirm the scope, then either add -exec rm {} \; or go ahead and enable the flag.

Common Pitfalls

  • find recurses the whole tree by default and can be slow on big directories; limit depth with -maxdepth or prune skipped dirs with -prune.
  • The -mtime N semantics vary: -3 is within the last 3 days, 3 is exactly 3 days ago, +3 is more than 3 days ago — mixing them up selects the wrong range.
  • -exec and -delete really change files; list matches without them first, then enable deletion or actions after confirming.
  • Symlinks are not followed by default; use -L or -follow if you need to, otherwise targets can be missed.
  • find matching differs from shell glob; quote patterns with single quotes so they are not expanded early when matching names with spaces.

Tips

  • find searches the current directory recursively by default; use -maxdepth 1 to limit it to the current directory only.
  • In -exec, {} stands for the found file; \; runs the command per file, while + batches them.
  • Preview with -print before deleting, to confirm matches and avoid accidental deletion.

FAQ

How do I choose between find -exec and xargs?

For small result sets and simple commands, run them inside find with -exec {} + or -exec {} \;. For large sets or complex per-item handling, pipe to xargs — be sure to combine -print0 on the find side with -0 on the xargs side, otherwise filenames containing spaces or newlines break the command.

How do I safely delete the files that find matches?

The safest way is adding -delete to the find command, which removes the matched files in place without going through an alias. If you need a pipeline, prefer find ... -print0 | xargs -0 rm. Avoid bare xargs rm or wrapping find in command substitution, which mishandles or fails on unusual filenames.

How do I find several file types (such as txt and log) at once with find?

Wrap the individual -name rules with the -o operator inside a pair of parentheses and pair that with the implicit -a, for example placing the -name for txt and the -name for log inside one parenthesized group followed by -type f. Without the parentheses, -o mixes with -a in a precedence that rarely matches what you intend.

Why does find -name differ from matching the full path?

-name matches only the base filename and ignores the directory part, whereas -path matches the full path. When filtering on multi-level paths or excluding directories, use -path together with -prune, and limit the scope with -maxdepth to avoid scanning the entire filesystem.

What do the sign and number mean for find -mtime and -mmin when filtering by modification time?

-mtime N selects files modified within the 24-hour window N days ago, -mtime -N means within the last N days, and -mtime +N means older than N days. For minute precision use -mmin, for example -mmin -30 selects files modified in the last 30 minutes. Note -mtime rounds to whole days, so boundary values are easy to misread.

Official References

Each command links to its official documentation below, so you can verify the latest usage and read deeper.

Maintained by LaoHand

Publicly updated on Jul 21, 2026, continuously proofread against official docs.

Contact Us

Wrong command or description? Send us corrections, business inquiries or product feedback by email.

Contact Us