terminal:scripting:find_xargs
Table of Contents
find and xargs
find predicates: filter by anything
find dir -name '*.txt' # glob on name (-iname case-insensitive) find dir -type f # f file, d dir, l symlink, s socket find dir -size +100M # >100M (also -10k, =size, c=M) find dir -mtime -7 # modified <7 days ago (+7 = older) find dir -newermt '2026-01-01' # date string version find dir -newer ref.txt # newer than a file find dir -perm -644 # at least these bits find dir -user brennan -group staff find dir -empty # empty files/dirs find dir -readable ! -writable
Combining & depth
find . -name '*.log' -o -name '*.tmp' # OR: group it: \( a -o b \) find . -name '*.log' -a -size +1M # AND (implicit -a) find . ! -name '*.md' # NOT find . -maxdepth 2 -type f # depth limit find . -path '*/node_modules' -prune -o -name '*.js' -print # skip subtree find . -regex '.*\.(jpg|png)' # full-path regex (-regextype posix-ext)
Acting on results
find . -name '*.tmp' -delete # careful: no undo find . -name '*.sh' -exec chmod +x {} \; # run per file find . -name '*.sh' -exec chmod +x {} + # batched: much faster find . -name '*.bak' -exec mv {} archive/ \; # {} = filename find . -type f -exec grep -l 'secret' {} + find . -newer marker -print0 | xargs -0 rm # safe for weird names
-exec cmd {} ; runs once per file. -exec cmd {} + batches like xargs :
prefer + on a 2-core machine (one process spawn, not thousands).
`-printf`: custom output
find . -type f -printf '%s %p\n' | sort -rn | head # biggest files find . -type f -printf '%T+ %p\n' | sort | tail # most recent find . -type d -empty -printf '%p\n'
xargs: feed a list to a command
find . -name '*.o' | xargs rm # rm a b c … batched cat urls.txt | xargs -n1 curl -sO # one arg per call echo a b c | xargs -n1 -I{} echo "item-{}" # {} placeholder find . -name '*.mp3' -print0 | xargs -0 -n1 -P4 loudnorm # parallel ×4 printf '%s\0' *.png | xargs -0 -n5 echo # 5 per invocation
-0pairs with-print0: spaces/newlines in names stay safe. Use it.-P4parallelism: on this dual-core,-P2to-P4is about right
(more just context-switches).
-I{}implies-n1; combine carefully.xargswith no input still runs the command once:-r/–no-run-if-empty
prevents that.
GNU parallel (if you want more)
sudo apt install parallel find . -name '*.jpg' | parallel convert {} {.}.webp parallel -j4 ffmpeg -i {} {.}.mp3 ::: *.wav
Recipes
# bulk rename extensions find . -name '*.jpeg' -exec bash -c 'mv "$1" "${1%.jpeg}.jpg"' _ {} \; # files modified today, copied out find ~ -type f -mtime -1 -print0 | tar --null -T - -cf ~/changed.tar # count lines across a tree find src -name '*.sh' -exec cat {} + | wc -l # dry-run discipline: always preview before -delete/-exec rm find . -name '*.tmp' -print # look first, then swap -print → -delete
See Also
terminal/scripting/find_xargs.txt · Last modified: by 127.0.0.1
