The combination of find and xargs is how you apply a command to
many files. The hazard is filenames with spaces, newlines, or
quotes — a class of bug that has deleted production data when
uncarefully composed.
find — predicate-based file selection
A find command is a series of predicates evaluated left to right.
The most-used predicates:
Predicate
Effect
-name '*.log'
Match by glob (case-sensitive)
-iname '*.log'
Case-insensitive name match
-type f
Regular file
-type d
Directory
-type l
Symbolic link
-size +100M
Larger than 100 MiB
-mtime -7
Modified in the last 7 days
-mtime +30
Modified more than 30 days ago
-user alice
Owned by user alice
-group admins
Owned by group admins
-perm -u+w
Writable by owner
-perm 0644
Exactly mode 0644
-newer reference
Modified after reference
! -name '*.gz'
Negate a predicate
Predicates can be combined implicitly (AND) or with explicit -or
and grouped with parens.
Read-only / Safefind old compressed logs— Find compressed log files older than 30 days. This is the predicate set behind most log-rotation cleanup tasks.
$ find /var/log -type f -name '*.gz' -mtime +30 | head
find can run a command on each match with -exec or pass them to
xargs:
Destructivedelete old logs— -delete is destructive. Verify the predicate set first by running without -delete. Always pipe to head or count results to confirm scope.
$ find /var/log -type f -name '*.gz' -mtime +30 -delete
Illustrative output
Read-only / Safefind -exec— -exec cmd {} + batches the matches and runs cmd once per batch (more efficient than {} \\;). {} is replaced with the file list. Always use + unless you specifically need per-file semantics.
$ find /var/log -type f -name '*.gz' -mtime +30 -exec ls -lh {} +
-rw-r--r-- 1 root root 12M Aug 1 06:25 /var/log/nginx/access.log.10.gz
-rw-r--r-- 1 root root 14M Aug 1 06:25 /var/log/nginx/access.log.11.gz
Illustrative output
xargs — feeding file lists into commands
xargs reads whitespace-separated tokens from stdin and invokes a
command with those tokens as arguments. The classic combination:
Read-only / Safefind piped to xargs— xargs takes the find output and passes it as arguments to ls. By default it runs ls once with as many files as fit in ARG_MAX.
$ find /var/log -type f -name '*.gz' | xargs ls -lh
-rw-r--r-- 1 root root 12M Aug 1 06:25 /var/log/nginx/access.log.10.gz
...
Illustrative output
Read-only / Safenull-delimited find + xargs— -print0 separates records with NUL bytes (which filenames cannot contain). xargs -0 reads that and passes each record as one argument. This is the production-safe pattern.
$ find /var/log -type f -name '*.gz' -print0 | xargs -0 ls -lh
-rw-r--r-- 1 root root 12M Aug 1 06:25 /var/log/nginx/access.log.10.gz
...
Illustrative output
locate — fast name search
locate is faster than find for simple name searches because it
queries a pre-built index (usually /var/lib/mlocate/mlocate.db or
/var/lib/plocate/plocate.db). The index is rebuilt periodically by
a daily cron job (the mlocate or plocate package).
Read-only / Safelocate— locate queries the file database. It does not see files created since the last index update; for recent files use find instead.