Skip to content

Find & Locate

find is one of the most powerful tools in Unix — it can locate files by any combination of name, size, age, permissions, or content, and immediately run commands on everything it finds.

Learning Objectives

  • Search for files by name, type, size, and modification time with find
  • Execute commands on found files using -exec and xargs
  • Use locate for fast filename searches
  • Use which, type, and command -v to find executables

find — Search the Filesystem

find /path -name "filename"        # find by exact name
find /path -name "*.log"           # wildcard in name
find /path -iname "*.LOG"          # case-insensitive
find /path -type f                 # files only
find /path -type d                 # directories only
find /path -type l                 # symlinks only

# Find all .log files under /var/log
find /var/log -name "*.log" -type f
/var/log/syslog
/var/log/auth.log
/var/log/kern.log
/var/log/dpkg.log

Searching by Size

find /home -size +100M              # larger than 100 MB
find /tmp -size -1k                 # smaller than 1 KB
find /var -size +10M -size -500M    # between 10 MB and 500 MB

Size suffixes: c (bytes), k (KB), M (MB), G (GB).

Searching by Modification Time

find /var/log -mtime -1             # modified in the last 1 day
find /home -mtime +30               # not modified in 30+ days
find /tmp -mmin -60                 # modified in the last 60 minutes
find /home -newer /etc/passwd       # newer than /etc/passwd

Searching by Permissions

find /home -perm 644                # exact permission match
find /home -perm -u+x               # at least executable by owner
find / -perm /4000 2>/dev/null      # setuid files
find /home -perm /o+w               # world-writable files (security check)

Executing Commands on Found Files

-exec — Run a Command on Each Match

find /tmp -name "*.tmp" -exec rm {} \;      # delete all .tmp files
find /home -name "*.sh" -exec chmod +x {} \;  # make scripts executable
find /var/log -name "*.log" -exec ls -lh {} \;  # list matching files

The {} is a placeholder for the matched file. \; ends the -exec expression.

# Using + instead of \; — passes all files at once (more efficient)
find /home -name "*.txt" -exec cat {} +

{}+ is faster than {}\;

-exec command {} \; runs the command once per file. -exec command {} + collects all files and runs the command once with all of them as arguments. Use + when the command accepts multiple file arguments.

xargs — Build and Execute Commands from stdin

xargs is often more flexible than -exec:

find /tmp -name "*.tmp" | xargs rm
find /home -name "*.sh" | xargs chmod +x
find . -name "*.py" | xargs grep -l "import os"

Filenames with spaces and xargs

If filenames contain spaces, xargs will split them incorrectly. Use null-delimited output:

find /home -name "*.txt" -print0 | xargs -0 grep "pattern"
-print0 outputs names separated by null bytes; -0 tells xargs to split on null bytes.


Combining find Conditions

find /home -name "*.log" -size +10M -mtime +7    # .log files, >10MB, >7 days old
find /home -name "*.tmp" -o -name "*.temp"        # either match (-o = OR)
find /home ! -name "*.keep"                        # NOT matching (! = negation)

locate searches a pre-built database instead of scanning the filesystem live. Much faster for simple name searches.

locate passwd              # find all files with "passwd" in the name
locate -i bashrc           # case-insensitive
locate "*.conf" | head -20 # find config files

locate database is updated daily

locate searches a database that is typically updated once a day by updatedb. Files created after the last update will not appear. Run sudo updatedb to refresh it immediately.


Finding Executables

which python3              # path to an executable in $PATH
type python3               # type: builtin, alias, function, or path
command -v python3         # POSIX-portable, returns path or nothing

which bash
/usr/bin/bash

# Find all python interpreters in $PATH
which -a python python3 2>/dev/null

Common Mistakes

find without -maxdepth on large trees

find / or find /home without constraints can take minutes on large filesystems and produce millions of results. Always add -maxdepth N, a name filter, or a path constraint when possible.

Forgetting 2>/dev/null on system-wide finds

Running find / or find /etc without 2>/dev/null will output many "Permission denied" errors for files owned by root. Redirect stderr to suppress them: find / -name "*.conf" 2>/dev/null.


Practice Exercises

Warm-Up (run and observe)

  1. Run find ~ -name "*.sh" -type f. How many shell scripts are in your home directory?
  2. Run find /var/log -mtime -1 -type f. What was modified in the last 24 hours?
  3. Run find /tmp -size +0 -type f. What non-empty files are in /tmp?

Main (write a short script)

Create ~/scripts/find_large.sh that finds files over a given size in a given directory:

#!/usr/bin/env bash
set -euo pipefail

DIR="${1:-.}"
SIZE="${2:-100M}"

echo "Files larger than $SIZE in $DIR:"
echo ""
find "$DIR" -type f -size "+$SIZE" -print0 \
    | xargs -0 ls -lh 2>/dev/null \
    | sort -k5 -rh \
    | awk '{ print $5, $9 }'

Stretch

  1. Use find to identify all world-writable files in /home (permissions include o+w). Why is this a security concern?
  2. Write a command using find and xargs that counts the total number of lines across all .py files under the current directory.
  3. Research find -prune. Use it to search a directory tree while excluding a specific subdirectory (e.g., search ~/projects but skip ~/projects/node_modules).

Interview Questions

  1. What is the difference between find and locate?
Show answer

find scans the filesystem in real time — it always returns current results but is slower. locate searches a pre-built database — it is much faster but may be out of date (updated daily by updatedb). Use locate for quick searches when a slightly stale result is acceptable; use find when accuracy is required or when you need to filter by attributes like size or modification time.

  1. What is the difference between -exec command {} \; and -exec command {} +?
Show answer

\; runs the command once per file found — if 1000 files match, the command runs 1000 times. + collects all matching files and passes them all to a single invocation of the command, like xargs. + is significantly faster for large result sets. Use + when the command accepts multiple arguments; use \; when the command can only process one file at a time.

  1. Why do you need -print0 with find and -0 with xargs?
Show answer

By default, find separates results with newlines and xargs splits on whitespace. Filenames can legally contain spaces and newlines, which would cause incorrect splitting. The null byte (\0) cannot appear in a filename, making it a safe delimiter. -print0 outputs filenames separated by null bytes; -0 tells xargs to split on null bytes instead of whitespace.


day05-part1-io-pipes | day01-part1-functions