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
Broken symlinks¶
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' {} +