The find command recursively searches directory trees for files and directories matching your criteria. It supports filtering by name, type, size, modification time, and permissions. Combined with -exec or xargs, find can apply any command to matched files in bulk, making it a powerful automation building block.
find . -name "*.log"
. is the starting point — use a specific path like /var/log to search from a different location.find . -iname "readme*"
-iname matches regardless of letter case, finding README.md, readme.txt, Readme.html, and all variants simultaneously. Useful when working with codebases that mix naming conventions.find . -type d -name "node_modules"
-type d to restrict results to directories only, -type f for regular files, and -type l for symlinks. This finds all node_modules directories — useful before packaging or disk cleanup.find . \( -name "*.py" -o -name "*.js" \)
-o for logical OR between conditions. Parentheses must be escaped with backslashes in the shell. This finds all Python and JavaScript files in the directory tree simultaneously.find . -size +10M
-size. The + prefix means "greater than". Units: k (KB), M (MB), G (GB). Use - for "less than". Great for finding disk-space hogs before cleanup.find . -mtime -7
-mtime -7 matches files modified within the last 7 days. Use +7 for files older than 7 days. Use -mmin -60 for files modified in the last 60 minutes.find . -type f -empty
-empty flag matches files with zero bytes. Combine with -type f to exclude empty directories. Useful for cleaning up placeholder files, failed downloads, or empty log files.find . -name "*.tmp" -delete
-delete action removes matched files. Always run find without -delete first to preview what will be removed. This is faster and safer than piping to rm via xargs for straightforward deletions.find . -name "*.sh" -exec chmod +x {} \;
-exec action runs a command for each match. {} is replaced with the filename; \; terminates the expression. This example makes all shell scripts in the tree executable.find . -name "*.py" -exec grep -l "TODO" {} \;
-l flag on grep prints only filenames with matches. Finds all Python files containing "TODO" — useful for code audits without a full IDE search.-type f or -type d to limit results to files or directories.-size, -mtime, or -perm to refine results.-exec command {} \; to process each result with any command.2>/dev/null to suppress "Permission denied" errors in restricted directories.find traverses all directories, including those you don't have permission to read. Suppress these errors by redirecting stderr: find . -name "*.log" 2>/dev/null. Alternatively, run with sudo when searching system directories.
-exec runs a new process for each matched file, which is slower for large result sets. xargs batches multiple filenames into fewer invocations. Use find . -name "*.txt" -print0 | xargs -0 grep "pattern" for better performance with filenames that may contain spaces.
Use -maxdepth N to limit recursion depth. For example, find . -maxdepth 2 -name "*.log" only searches the current directory and its immediate subdirectories. Use -mindepth to skip top-level results.