#

Commands

Subscribe
Commands October 29, 2026·10 min read

How to Find Files in Linux with the find Command

Use GNU find to locate files or directories by name or filesystem attributes. Start in the smallest directory that should contain them, add the filters you need, and check the results before acting on them. If you need to search inside files, consult a filename index, or choose a path interactively, another tool fits better.

Find a file by name

find file name

Run find . -type f -name 'report.txt' to look for a regular file named report.txt in your current directory and its subdirectories. The . is the current directory, -type f selects regular files, and -name matches the filename. To look for files with a given extension, use a quoted wildcard such as '*.log'.

Match names, paths, extensions, and file types

linux filename patterns

GNU find matches filenames with shell-style wildcard patterns, called globs. The -name test checks the basename, which is the last component of a path. Regular expressions use a different syntax and a different matching mechanism.

To find regular files ending in .mp4, run:

find . -type f -name '*.mp4'

The asterisk matches any sequence of characters before .mp4. Quote the pattern so your shell passes the asterisk to find unchanged. Unquoted, it can expand against files in the current directory first.

For -name, the ending pattern is '*.mp4', and an expression with regex anchors such as '^.*\.mp4$' is treated as a glob. A poster in an r/bash discussion about selecting .mp4 files described a failed attempt: "This one did NOT work. But I would've preferred to use it, since it didn't need a wildcard; I knew that all the files I wanted to delete indeed ended with .mp4, didn't merely include it."

Search taskExample
Ignore filename casefind . -type f -iname 'report.txt'
Find log filesfind /var/log -type f -name '*.log'
Find directories named cachefind . -type d -name 'cache'
Match a path through a logs directoryfind . -type f -path '*/logs/*.log'
Find symbolic linksfind . -type l -print
filename type filters

Say a project contains app/logs/error.log and app/archive/error.log. The basename match '*.log' selects both. The path test '*/logs/*.log' adds the directory, which narrows the match to the logs folder when the same filename appears in several places.

-type filters by kind: f is a regular file, d a directory, and l a symbolic link under the default link policy. Use -iname when you're unsure of the capitalization, then check whether the extra matches belong in your result.

Choose where find searches

linux search directories

find only searches the directory you give it. If the file is somewhere else, even a perfect pattern returns nothing.

  • Current directory: . searches from the directory your terminal is in.
  • Home directory: "$HOME" searches everything under your home directory.
  • Specific directory: a path such as /var/log or a project folder limits the search to that location.
  • Filesystem root: / starts a broad search. Use it only when the file could be outside any narrower tree. It takes longer and produces more permission errors, and it can reach unusual filesystems.

An r/LinuxTeck poster described the failure this way: "Embarrassing but true, I was using find with the wrong path the whole time." Check your starting directory before rewriting your pattern. To see where your terminal is working, run:

pwd

For a known project, start at its parent directory to avoid scanning unrelated files.

Limit search depth

recursive search scope

GNU find descends into every subdirectory by default. Add -maxdepth to limit how many levels it goes down:

find . -maxdepth 1 -type f -print

This selects regular files directly in the current directory and skips files in its subdirectories. The related -mindepth option sets the minimum depth at which tests and actions apply.

Find files by size or modification time

file size timestamps

Modification-time filters

To find regular text files modified less than 60 minutes ago, use:

find . -type f -name '*.txt' -mmin -60 -print

-mmin tests how many minutes ago a file's content last changed. GNU -mtime counts that age in 24-hour periods, with documented rounding behavior. So -mtime 1 means an elapsed-age range, not a calendar day such as yesterday.

File-size filters

To find regular files above a +10M threshold:

find . -type f -size +10M -print

In GNU find, uppercase M means units of 1,048,576 bytes, or one mebibyte. The size test rounds up to the chosen unit before it compares.

modification time filtering
  • +n: values greater than n.
  • -n: values less than n.
  • n: exactly n units, after rounding.

If a file near your threshold is missing, compare its size or timestamp with the unit and range in the expression.

Exclude directories and limit unnecessary traversal

exclude directory traversal

GNU -prune stops find from descending into selected directories. Use it to skip generated or vendored subtrees in a project.

To find .txt files while skipping every directory named node_modules, use:

find . -type d -name node_modules -prune -o -type f -name '*.txt' -print

The expression has two branches. The left one matches a node_modules directory and prunes it. -o means OR, so the right branch runs for everything the left one didn't match, and it prints the regular .txt files.

prune search expression

Pruning changes which directories find explores. Filtering a finished list of paths would still scan the unwanted subtrees and only hide their output.

-xdev also stops find from descending into directories on other filesystems.

Check hidden files and symbolic links

hidden symbolic links

GNU find reaches files inside hidden directories without an extra switch, as long as you can access them and they sit under your starting directory.

Symbolic links behave differently. With the default -P behavior, GNU find doesn't descend into a directory just because a symlink points to it.

Take this layout:

project/
├── .hidden/
│   └── settings.conf
├── config/
│   └── app.conf
└── linked-config -> config/

A normal search from project/ finds both files in the real directories, including .hidden. To follow a symlink to a directory, GNU find supports -L:

find -L . -type f -name '*.conf' -print
follow directory symlinks

Put -L before the starting directory. Following directory links can reach extra locations and can enter symbolic-link loops.

To check whether a directory is a link, run:

ls -ld linked-config

The GNU find(1) manual documents the link policies and their effects on traversal and file-type tests.

Why does find return nothing or show permission errors?

find command troubleshooting

Empty output means nothing matched. Check the starting directory first, then each filter. A missing match can come from a starting directory that was too narrow, a name test that didn't match, or permissions that blocked traversal.

SymptomCauseWhat to check
Known file is missingWrong starting directoryCurrent directory and the file's parent
Too few matchesCase, type, size, or time filterWhich test excludes the file
Nested files disappearDepth limit or pruned directory-maxdepth and pruning branches
Files under a linked directory are missingSymbolic-link policyWhether the directory is a link, and whether you need -L
Permission errors appearInaccessible directories or filesStandard error and exit status

Work through a missing-file example

Say you expect report.txt somewhere in your home directory, but you start with:

find "$HOME/Documents" -type f -name 'report.txt'

That command can't see "$HOME/Projects". Widen the starting directory and keep the name test as it is:

find "$HOME" -type f -name 'report.txt'

If it shows up now, your first search started in the wrong place. If the wider search is still empty, remove the other restrictive tests one at a time. A size or time condition, for example, can exclude a file whose name is correct.

permission error diagnosis

Read errors before interpreting the result

GNU find writes diagnostic messages to standard error. Check the exit status right after the search:

find "$HOME/Documents" -type f -name 'report.txt'
printf 'Exit status: %s\n' "$?"

$? holds the status of the most recent command, so the status-printing command must come right after find, with nothing in between. A nonzero status means errors occurred. The paths find printed are still valid matches.

Searching the whole system with sudo doesn't guarantee a clean run either. A poster in r/linux4noobs wrote: "So sometimes when I run something in entire system as sudo, I still see “permission denied”"

2>/dev/null only hides the standard-error messages and doesn't change what find can access. Keep the messages visible while you decide whether the directory tree was actually searched.

Inspect and process the files you find

safe filename processing

Run -print first and read the list before handing the paths to another command:

find . -type f -name '*.txt' -print

Plain -print output is fine for reading in a terminal. Linux filenames can contain spaces and newlines, so line-separated output isn't a reliable format for other programs.

A shell loop like for f in $(find ...) can split one filename into several words. When another command consumes the matches, pass them in a way that keeps each path intact.

Pass matches directly with -exec

To list the matching text files:

find . -type f -name '*.txt' -exec ls -ld -- {} +
  • -exec: runs an external command on the matched paths.
  • {}: marks where the paths go.
  • +: lets GNU find batch many paths into one command run.
  • ls -ld --: shows information about the given paths, using GNU ls syntax.

This passes the paths as arguments without shell word splitting. On directory trees that other users can modify while the command runs, -exec still has pathname-resolution race risks. GNU documents -execdir as a safer alternative there, with its own command-search-path requirements.

filename argument safety

Use NUL-delimited output with a compatible consumer

-print0 in GNU find separates pathnames with NUL characters. GNU xargs -0 reads that format and keeps each path whole, even when names contain spaces or newlines.

find . -type f -name '*.txt' -print0 |
  xargs -0 -r ls -ld --

-0 selects NUL-delimited input, and -r stops xargs from running the command when there are no matching paths. The -- option belongs to GNU ls, so any other command uses its own argument syntax.

In Bash, a pipeline reports the exit status of xargs by default. Run set -o pipefail first if you also need a failure in find to show in the pipeline's status.

Keep deletion outside the discovery step

Do not append -delete to a working prune-and-print expression to turn it into a deletion command. In GNU find, -delete implies depth-first traversal through -depth, which defeats the usual exclusion behavior of -prune.

When to use grep, locate, or another search tool

linux search utilities
Your taskTool to consider
Find entries by name, type, size, or agefind
Search text inside filesgrep or ripgrep
Look up a filename in an indexlocate
Use an alternative filename-search interfacefd
Choose a path interactivelyfzf

Finding .log files is a job for find. Searching them for ERROR is a job for grep or ripgrep. Some document formats need text extraction or a format-specific tool before their contents can be searched.

locate reads filenames from an existing index instead of scanning the live tree on every lookup. The index can lag behind filesystem changes. which and whereis find commands and executables, a narrower job than finding arbitrary files.

search result verification
NoScript Team