find: locate files by name, size and date
ls shows one folder. find searches a folder and everything below it for files that fit a description: a name, a kind, a size, an age. It is the terminal's search tool, and one of the most useful commands to know well.
The shape of the command
find takes where to look, then what to look for.
asha@pc:~/demo$ find . -name "notes.txt"
./notes.txtThe dot means "start here". The result is the path to each match.
With no conditions at all, find lists everything below the starting point.
asha@pc:~/demo$ find .
.
./log.txt
./marks.csv
./notes.txt
./old
./old/draft.txt
./photos
./photos/beach.jpg
./photos/hills.jpg
./report.txtBy name
-name matches the file name. Wildcards are allowed, and must be in quotation marks so that find receives them, not the shell.
asha@pc:~/demo$ find . -name "*.txt"
./log.txt
./notes.txt
./old/draft.txt
./report.txt
asha@pc:~/demo$ find . -name "*.jpg"
./photos/beach.jpg
./photos/hills.jpg-iname does the same and ignores capital and small letters.
asha@pc:~/demo$ find . -iname "BEACH*"
./photos/beach.jpgBy type
| Test | Finds |
|---|---|
-type f | ordinary files |
-type d | folders |
-type l | links |
asha@pc:~/demo$ find . -type d
.
./old
./photos
asha@pc:~/demo$ find . -type f -name "*.csv"
./marks.csvConditions written one after another must all be true.
By size
-size takes a number and a unit: k for kilobytes, M for megabytes, G for gigabytes. A plus means "larger than" and a minus "smaller than".
asha@pc:~/demo$ find . -type f -size +100c
./log.txt
asha@pc:~/demo$ find . -type f -size -60c
./marks.csv
./notes.txt
./old/draft.txt
./photos/beach.jpg
./photos/hills.jpgThe c unit means bytes, used here because the sample files are tiny. In real use, find . -size +100M finds files over 100 megabytes, a quick way to see what is filling a disk.
By age
-mtime counts days since the file was last changed. -mtime -7 means changed in the last seven days, and -mtime +30 more than thirty days ago. -mmin does the same in minutes.
asha@pc:~/demo$ find . -type f -mtime +1
./log.txt
./marks.csv
./notes.txt
./old/draft.txt
./photos/beach.jpg
./photos/hills.jpg
./report.txt-newer file finds everything changed more recently than a given file.
Limiting the depth
-maxdepth 1 looks only in the starting folder, not below it.
asha@pc:~/demo$ find . -maxdepth 1 -type f
./log.txt
./marks.csv
./notes.txt
./report.txtEither, or not
-o means "or", and ! means "not". Brackets group conditions and need a backslash in front.
asha@pc:~/demo$ find . -type f \( -name "*.txt" -o -name "*.csv" \)
./log.txt
./marks.csv
./notes.txt
./old/draft.txt
./report.txt
asha@pc:~/demo$ find . -type f ! -name "*.txt"
./marks.csv
./photos/beach.jpg
./photos/hills.jpgDoing something with the results
-exec runs a command on each file found. The pair of curly brackets stands for the file, and the command ends with \;.
asha@pc:~/demo$ find . -name "*.txt" -exec wc -l {} \;
8 ./log.txt
3 ./notes.txt
1 ./old/draft.txt
5 ./report.txtA common use is searching inside the files found:
asha@pc:~/demo$ find . -name "*.txt" -exec grep -l -i total {} \;
./report.txtEnding with + in place of \; passes all the files to one run of the command, which is faster: find . -name "*.txt" -exec grep -l total {} +.
Deleting what you find
find can delete, with -delete or -exec rm.
Danger. find with -delete removes every match at once, with no questions and no undo. A mistake in the conditions, or -delete placed before them, deletes far more than intended: find . -delete -name "*.tmp" deletes everything, because the delete happens before the name is tested. Always run the command without -delete first and read the list. Only then add -delete at the very end.
The safe sequence:
asha@pc:~/demo$ find . -type f -name "*.jpg"
./photos/beach.jpg
./photos/hills.jpgRead the list. If it is exactly what you mean to remove, repeat the command with -delete added last. For an extra check, -ok rm {} \; asks before each file.
Counting
asha@pc:~/demo$ find . -type f | wc -l
7Errors while searching
Searching from / produces many "Permission denied" lines for folders you may not read. Hide them by sending error messages nowhere: find / -name "hosts" 2>/dev/null.
Faster searching by name
find reads the disk each time, which is thorough and can be slow on a whole system. Many Linux systems have locate filename, which looks in an index built once a day and answers instantly, though it does not know about very new files. The Mac has mdfind, which uses the Spotlight index: mdfind -name report.
A few recipes
| To find | Command |
|---|---|
| files changed today | find . -type f -mtime -1 |
| the largest files | find . -type f -size +500M |
| empty files | find . -type f -empty |
| empty folders | find . -type d -empty |
| files belonging to a user | find . -user asha |
| everything except one folder | find . -path ./old -prune -o -type f -print |
On Windows, dir /s /b pattern and where /r do the simpler part of this job.
Examples shown with output were run on 12 November 2026 in a practice folder: Windows commands in cmd.exe on Windows 11, Linux commands with the GNU tools of Git Bash. The folder path and user name were replaced with made-up ones. Commands marked "not run here" are shown as you would type them.
This is an independent learning site. It is not connected with Microsoft, Apple or any Linux distribution. Windows, macOS and other names belong to their owners. Try commands first in a practice folder, never on files you cannot afford to lose.