Andrew Mercer
on this page

Basics

find . -name '*.txt'                   # quote the pattern so the shell does not expand it first
find / -name 'account-server.conf' 2>/dev/null     # hide permission-denied noise
find /tmp "$HOME" . -name 'notes*'     # search several starting points
find . -iname 'report*'                # case-insensitive
find . -name 'a' -o -name 'b'          # OR (use \( ... \) grouping with other tests)
find . ! -name '*.mp3' ! -name '*.flac' ! -name '*.ogg' -type f     # NOT
find . -iname 'T????????'              # 'T' followed by exactly 8 characters
find . -regex '.*/glance/api\.log'     # regex matches the whole path
find . -inum 274844                    # by inode number (add -xdev to stay on one filesystem)

By type and depth

find . -type d                         # directories;  f = files, l = symlinks
find . -maxdepth 1 -type d             # do not recurse
find . -type d -exec chmod 0755 {} +
find . -type f -exec chmod 0644 {} +

-exec ... {} + passes many files to one command invocation and is faster than \;, which runs the command once per file.

Excluding directories

find / -path /proc -prune -o -path /sys -prune -o -type f -mtime -1 -print
find / -xdev -type f -size +100M           # stay on the root filesystem only

By age

-mtime counts days, -mmin minutes; -N means less than N, +N more than N.

find / -mmin -10                            # modified in the last 10 minutes
find . -xdev -type f -mmin +180             # older than 3 hours
find /path -type f -mtime -1                # modified within the last day
find /path -type f -mtime +7 -print         # older than 7 days
find /path -type f -mtime +7 -delete        # delete files older than 7 days

By size

find . -size +100M                          # larger than 100 MB
find . -xdev -type f -size +20M -mmin -10 -exec ls -lh {} +
find . -type f -size +50M -printf '%s %p\n' | sort -nr | head       # largest files
find . -empty -type f                       # empty files;  -type d for empty directories
find . -xtype l                             # symlinks whose target is missing
find . -xtype l -delete

Delete safely

Preview first, then run the real command:

find / -name core -exec echo rm -f {} \;   # dry run: prints what would be removed
find / -name core -delete                    # or: -exec rm -f {} +
find . -type l -delete                       # delete every symlink under here

-delete implies -depth, and the order of options matters: put tests before -delete, or it deletes everything visited. Names with spaces and newlines break find | xargs rm; use -print0 | xargs -0 or -exec.

Rename in place

find . -type f -name rhel.yaml -execdir echo mv {} redhat.yaml \;    # test
find . -type f -name rhel.yaml -execdir mv {} redhat.yaml \;         # run

For bulk renaming patterns see rename.

Move all files ending in .[ filetype ]

find [ source_dir ] -type f -name '*.pdf' -exec mv -n -t [ dest_dir ] {} +

Security audits

World-writable files that are not symlinks, sockets, or sticky directories:

find / -xdev \( -path /proc -o -path /sys \) -prune -o \
     -perm -0002 ! -type l ! -type s ! \( -type d -perm -1000 \) -print

Setuid/setgid binaries:

find /usr -xdev -type f \( -perm -u+s -o -perm -g+s \) -print0 | xargs -0 ls -l

Review unexpected entries in either list.

Combine with other tools

find . -name '*.log' -print0 | xargs -0 grep -l 'ERROR'
find . -type f -name '*.sh' -exec grep -l '^#!/.*bash' {} +

See xargs and grep.