grep -l and -L: List Files With or Without a Match
grep -l prints only the names of files that contain a match; grep -L prints the names of files that do not.
When you care which files contain (or lack) a pattern rather than the lines themselves, -l and -L give you a clean filename list to act on.
What it does
grep -l (--files-with-matches) prints each filename that has at least one match, once, and stops scanning that file early. grep -L (--files-without-match) is the complement: it prints filenames that contain no match. Both pair naturally with -r for tree-wide checks.
Common usage
# which source files mention a deprecated symbol
grep -rl "oldFunction" src/
# which files are MISSING a required license header
grep -L "SPDX-License-Identifier" src/*.go
# feed the list into another command
grep -rl "console.log" src/ | xargs -r sed -i '/console.log/d'Options
| Flag | What it does |
|---|---|
| -l / --files-with-matches | Print filenames that contain a match |
| -L / --files-without-match | Print filenames with no match |
| -r | Recurse so -l/-L cover a tree |
| -Z / --null | NUL-separate names for safe xargs -0 |
In CI
A license or header check is naturally grep -L: if it prints any filename, those files are missing the header and the step should fail. When piping names into xargs, add -Z to grep and -0 to xargs so filenames with spaces survive.
Common errors in CI
Remember the exit code reflects matches, not the printed list: grep -L exits 0 if the underlying pattern matched somewhere, so drive failure off whether it printed filenames ([ -n "$(grep -L ...)" ]), not off the exit status. Filenames with spaces break naive xargs; use -Z plus xargs -0.