Skip to content
Latchkey

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

Terminal
# 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

FlagWhat it does
-l / --files-with-matchesPrint filenames that contain a match
-L / --files-without-matchPrint filenames with no match
-rRecurse so -l/-L cover a tree
-Z / --nullNUL-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.

Related guides

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