Skip to content
Latchkey

grep -l Into xargs: Act on Matching Files

grep -l lists the files that contain a pattern, and xargs runs a command on each of them.

A common bulk-edit pattern is "find every file mentioning X and do Y to it". grep -l finds them; xargs applies the action.

What it does

grep -rl <pattern> prints the names of files that contain at least one match, one per line. Piped into xargs, those names become arguments to your command. For safety with odd filenames, grep -rlZ emits NUL-terminated names to pair with xargs -0.

Common usage

Terminal
# replace a string in every file that contains it
grep -rlZ 'OLD_API' . | xargs -0 -r sed -i 's/OLD_API/NEW_API/g'
# count lines in every file mentioning TODO
grep -rl TODO src | xargs wc -l

Options

FlagWhat it does
grep -lPrint only names of files with a match
grep -rRecurse into directories
grep -ZNUL-terminate the filenames (pair with xargs -0)
xargs -0Read those NUL-terminated names safely
xargs -rDo nothing if grep found no files

In CI

Add -r to xargs so an empty grep result does not run sed (or your command) with no files. Use grep -lZ with xargs -0 so a matching path with spaces does not get split. This combination is the safe default for codemods in a pipeline.

Common errors in CI

Without -Z/-0, a matching file named "old config.js" splits into "old" and "config.js" and sed reports "can't read old: No such file or directory". Without -r, an empty match list makes sed wait on stdin or error. grep exits 1 when nothing matches, so guard the pipeline if a no-match run should not fail the step.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →