find Command Cheat Sheet
find . -name '*.log' # by name (case-sensitive)
find / -iname 'nginx.conf' 2>/dev/null # case-insensitive, hide permission errors
find . -type f -mtime -7 # files changed in the last 7 days
find / -xdev -type f -size +1G # files over 1 GiB on this filesystem
find . -type f -name '*.tmp' -delete # delete matches (test without -delete first)
find . -type f -exec grep -l 'TODO' {} + # run a command on the results
Syntax: find [starting-point...] [tests] [actions]. The starting point defaults to the current directory, and the default action is -print. Tests are combined with an implicit AND. This page covers GNU find from findutils, the version on all mainstream distros.
By name and path
| Command | What it does |
|---|---|
find . -name 'file.txt' | Exact name, case-sensitive |
find . -iname '*.jpg' | Case-insensitive glob (.JPG, .jpg) |
find . -path '*/cache/*' | Match against the whole path, not just the name |
find . -regex '.*\.\(jpg\|png\)' | Regex on the whole path (Emacs syntax by default) |
find . -regextype posix-extended -regex '.*\.(jpg|png)' | Same with extended regex |
find . -not -name '*.bak' | Negate a test (! also works) |
find . \( -name '*.c' -o -name '*.h' \) | OR with grouping (escape the parentheses) |
find . -maxdepth 1 -name '*.sh' | Do not descend into subdirectories |
find . -mindepth 2 | Skip the first levels |
find . -name .git -prune -o -type f -print | Skip a directory entirely |
find / -xdev -name core | Stay on one filesystem (skip /proc, /sys, other mounts) |
By type, size and emptiness
| Command | What it does |
|---|---|
find . -type f | Regular files only |
find . -type d | Directories only |
find . -type l | Symbolic links |
find . -xtype l | Broken symlinks |
find . -type f,d | Files or directories (GNU) |
find . -size +100M | Larger than 100 MiB (k, M, G suffixes) |
find . -size -10k | Smaller than 10 KiB |
find . -size +100M -size -1G | Between 100 MiB and 1 GiB |
find . -empty | Empty files and empty directories |
find . -type d -empty -delete | Remove empty directories |
By time
-mtime counts in 24-hour periods, -mmin in minutes. -N means "less than N ago", +N "more than N ago".
| Command | What it does |
|---|---|
find . -mtime -1 | Content modified in the last 24 hours |
find . -mtime +30 | Modified more than 30 days ago |
find . -mmin -15 | Modified in the last 15 minutes |
find . -atime +90 | Not accessed for 90 days (unreliable with noatime/relatime) |
find . -ctime -1 | Metadata (permissions, owner) changed in the last day |
find . -newer ref.txt | Modified more recently than a reference file |
find . -newermt '2026-10-01' | Modified after a date |
find . -newermt '2026-10-01' ! -newermt '2026-10-08' | Modified within a date range |
find . -daystart -mtime 0 | Modified today (since midnight) |
By owner and permissions
| Command | What it does |
|---|---|
find . -user alice | Owned by a user |
find . -group www-data | Owned by a group |
find / -nouser -o -nogroup | Files with no valid owner or group (left over from deleted users) |
find . -perm 644 | Exactly mode 644 |
find . -perm -u+x | At least these bits set (user-executable) |
find . -perm /o+w | Any of these bits set (world-writable) |
find / -xdev -perm -4000 -type f | SUID binaries (security audit) |
find . -readable / -writable / -executable | Files the current user can actually access |
Permission numbers explained: Linux file permissions guide and the chmod calculator.
Actions
| Command | What it does |
|---|---|
find . -name '*.log' -print | Print paths (the default) |
find . -name '*.log' -ls | Print in ls -dils format |
find . -type f -printf '%s %p\n' | Custom output: size and path (%TY-%Tm-%Td for date, %u owner, %m mode) |
find . -print0 | NUL-separated output for xargs -0 |
find . -name '*.tmp' -delete | Delete matches (implies -depth) |
find . -name '*.sh' -exec chmod +x {} + | Run one command with many files at once |
find . -name '*.sh' -exec chmod +x {} \; | Run the command once per file |
find . -name '*.conf' -ok rm {} \; | Ask for confirmation before each command |
find . -type d -execdir ... | Run the command from the file's own directory (safer) |
find . -name x -quit | Stop after the first match |
Common recipes
Largest files on the system when you hit No space left on device (a full script is in find largest files):
sudo find / -xdev -type f -size +200M -printf '%s\t%p\n' 2>/dev/null | sort -rn | head -20 | numfmt --field=1 --to=iec
Delete log files older than 14 days, after checking what would be removed:
find /var/log/myapp -type f -name '*.log' -mtime +14 -print
find /var/log/myapp -type f -name '*.log' -mtime +14 -delete
Fix permissions on a web root: directories 755, files 644:
find /srv/www -type d -exec chmod 755 {} +
find /srv/www -type f -exec chmod 644 {} +
Search file contents only in certain files:
find . -type f -name '*.yaml' -exec grep -Hn 'image:' {} +
Handle names with spaces safely using xargs:
find . -type f -name '*.png' -print0 | xargs -0 -r optipng -o2
Archive files changed in the last week (see the tar cheat sheet):
find ~/projects -type f -mtime -7 -print0 | tar --null -T - -czf recent.tar.gz
Count files per extension:
find . -type f -name '*.*' | sed 's/.*\.//' | sort | uniq -c | sort -rn | head
Find and remove broken symlinks:
find /usr/local/bin -xtype l -print -delete
Gotchas
- Quote the pattern.
find . -name *.txtlets the shell expand*.txtfirst; if a matching file exists in the current directory you search for that exact name, or get "paths must precede expression". Write-name '*.txt'. -exec ... {} +vs{} \;.+batches many paths into one command (fast, avoids Argument list too long) but{}must be the last argument before+.\;runs once per file and allows{}anywhere; escape or quote the semicolon so the shell doesn't eat it.- Order matters for
-delete.find . -delete -name '*.tmp'deletes everything, because-deleteruns before the name test. Put-deletelast, and run the command with-printfirst. -oneeds parentheses.find . -name '*.c' -o -name '*.h' -exec rm {} +only applies-execto.hfiles, because AND binds tighter than OR. Wrap the alternatives in\( ... \).-sizerounds up.-size -1Mmeans "0 blocks of 1 MiB", which only matches empty files. Use-size -1024k.-mtime +1means at least 2 days. find drops the fractional part of the age, so "+1" is more than one full day, i.e. 48 hours or older.- Permission denied noise. Searching
/as a normal user prints many errors; add2>/dev/nullor usesudo.
Reference: find(1). For searching inside files, see the grep cheat sheet.
Frequently asked questions
How do I find a file by name in Linux?
Use find / -name 'file.txt' 2>/dev/null, or -iname for a case-insensitive match. Quote patterns with wildcards: find . -name '*.log'.
What is the difference between -exec {} \; and -exec {} +?
\; runs the command once per file. + passes many files to one command invocation, which is much faster and avoids Argument list too long.
How do I find files modified in the last 24 hours?
find . -type f -mtime -1, or -mmin -60 for the last hour.
How do I find large files on Linux?
find / -xdev -type f -size +500M -exec ls -lh {} + 2>/dev/null lists files over 500 MB on the root filesystem.
Is find faster than locate?
No. locate (plocate on current distros) searches a prebuilt database and is nearly instant, but it can be out of date. find walks the disk every time and is always current.
Spotted a mistake or a command that no longer works? Send a correction — pages are re-checked when reports come in.