Skip to content

/commands/find/find-file-by-name

find . -name "*.log": find files by name or extension

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · find (GNU findutils) 4.11.0updated
tool
find
versions
GNU findutils 4.x, BSD find (macOS)
os
linux, macos, windows

find . -name "*.log" lists every file and directory below the current directory whose name matches *.log. Put the pattern in quotes so the shell does not expand it, use -iname to ignore case, add -type f to keep only regular files, and replace . with the directory to search (for example find /etc -name nginx.conf). The pattern is a shell glob matched against the file name only, not the full path.

Example

bash
mkdir -p app/logs app/src old
touch app/logs/server.log app/logs/Error.LOG app/src/main.py app/README.md old/app.log.1
mkdir app/archive.log
find . -name '*.log' | sort
echo ===
find . -type f -iname '*.log' | sort
echo ===
find . -name '*.log*' -not -path './old/*' | sort

Output

./app/archive.log
./app/logs/server.log
===
./app/logs/Error.LOG
./app/logs/server.log
===
./app/archive.log
./app/logs/server.log

The first search also returns the directory archive.log, because -name matches directories too. -type f -iname keeps only files and matches Error.LOG regardless of case. The third command widens the glob and excludes everything under ./old.

Common forms

CommandFinds
find . -name 'nginx.conf'Files or directories named exactly nginx.conf
find . -type f -name '*.py'Regular files ending in .py
find . -iname '*.jpg'Ignoring case: .jpg, .JPG, .Jpg
find . -type d -name node_modules -prunenode_modules directories, without descending into them
find . -name '*.js' -not -path '*/node_modules/*'JavaScript files outside node_modules
find . \( -name '*.jpg' -o -name '*.png' \)Either extension; the parentheses group the -o
find . -maxdepth 1 -name '*.txt'Only in the current directory, not below
find / -name hosts 2>/dev/nullSearch the whole system and hide Permission denied lines
find . -regex '.*/[0-9]+\.csv'Full path matched with a regex (GNU default: emacs syntax)

Act on the results

bash
mkdir -p proj/a proj/b
printf 'one\n' > proj/a/x.txt
printf 'two\nthree\n' > proj/b/y.txt
find proj -name '*.txt' -exec wc -l {} + | sort -k2
find proj -name '*.txt' -print0 | xargs -0 grep -l three

Output

 1 proj/a/x.txt
 2 proj/b/y.txt
 3 total
proj/b/y.txt

-exec cmd {} + runs one command with many file names; -print0 | xargs -0 does the same and survives names with spaces and newlines. Both avoid Argument list too long.

Pitfalls

  • Unquoted globs. find . -name *.log works only while no .log file exists in the current directory; with two of them find stops with paths must precede expression.
  • Option order. -maxdepth is a global option: put it right after the path, or GNU find warns that it was specified after -name.
  • -o without parentheses. find . -name '*.jpg' -o -name '*.png' -exec ... applies -exec only to the PNG files, because -a binds tighter than -o. Group the names with \( ... \).
  • macOS. BSD find needs a path (find . -name x, not find -name x) and does not have every GNU option, but -name, -iname, -path, -type, -maxdepth and -prune work the same.

If the database-backed locate command is installed, locate nginx.conf is faster for whole-system lookups, but it only knows files that existed when its index was last updated.

FAQ

Why does find -name *.log fail with paths must precede expression?

Without quotes the shell expands *.log to the matching names in the current directory before find runs, so find receives several words after -name. Quote the pattern, find . -name '*.log', so find does the matching itself in every directory.

How do I hide the Permission denied lines when searching from /?

Send standard error to /dev/null, find / -name nginx.conf 2>/dev/null. The messages come from directories your user cannot read; the search continues past them.

How do I match the full path instead of the file name?

Use -path, as in find . -path '*/config/*.yml'. -name only looks at the last part of the path, so a pattern with a slash in it never matches -name.

Sources