/commands/grep/grep-invert-match
grep -v: exclude lines that match a pattern (invert match)
- tool
- grep
- versions
- GNU grep 3.x
- os
- linux, macos, windows
grep -v pattern file prints every line that does not match the pattern, so it removes lines from the output. Typical uses: grep -v DEBUG app.log hides debug messages, grep -v '^#' config drops comment lines, and ps aux | grep nginx | grep -v grep hides the grep process itself. Combine it with -e or -E to exclude several patterns at once.
Example
cat > app.conf <<'EOF'
# main settings
port = 8080
# logging
level = info
# indented comment
name = demo
EOF
grep -v '^#' app.conf
echo ===
grep -Ev '^[[:space:]]*(#|$)' app.conf
echo ===
grep -vc '^#' app.confOutput
port = 8080 level = info # indented comment name = demo === port = 8080 level = info name = demo === 5
The first command removes lines that start with # but keeps the empty lines and the indented comment. The second uses one extended regex for lines that are empty or start with optional blanks and #, and prints only the settings. -vc counts the lines that do not match.
Common forms
| Command | Keeps |
|---|---|
| grep -v DEBUG f | Lines without DEBUG |
| grep -v -e DEBUG -e TRACE f | Lines with neither DEBUG nor TRACE |
| grep -Ev 'DEBUG|TRACE' f | Same, with an extended regex |
| grep -v '^$' f | Non-empty lines |
| grep -Ev '^[[:space:]]*(#|$)' f | Lines that are not comments or blank |
| grep -vi warning f | Lines without warning in any case |
| grep -vw id f | Lines without the whole word id (keeps lines with valid or ids) |
| grep -vF -f stop.txt f | Lines containing none of the fixed strings listed in stop.txt |
| grep ERROR f | grep -v timeout | ERROR lines except timeouts |
Remove the lines of one file from another
printf '%s\n' ada bob cyd dan > all.txt
printf '%s\n' bob dan > done.txt
grep -vxF -f done.txt all.txtOutput
ada cyd
-f done.txt reads the patterns from a file, -F treats them as fixed strings and -x makes each pattern match a whole line, so bob does not also remove bobby. The result is the lines of all.txt that are not in done.txt.
Pitfalls
- An empty pattern file excludes nothing:
grep -v -f empty.txtprints every line, because no pattern can match. - Windows line endings: a pattern file saved with CRLF endings has a
\rat the end of each pattern, so-xnever matches. Convert it withtr -d '\r'first. - Exit status: grep -v exits 0 when it printed at least one line and 1 when every line matched, which can stop scripts that use
set -e. -vwith-oprints nothing, because there is no matching part to show in a line that does not match.
For deleting lines in place rather than filtering output, sed -i '/pattern/d' file does the same selection and rewrites the file.
FAQ
How do I exclude several patterns at once?
Give every pattern with -e, as in grep -v -e DEBUG -e TRACE file, or use one extended regex, grep -Ev 'DEBUG|TRACE' file. A line is printed only if it matches none of them.
Why does grep -v exit with status 1 when it printed nothing?
The exit status reports whether any line was selected. With -v the selected lines are the ones that do not match, so status 1 means every input line matched the pattern. In scripts with set -e, add || true where an empty result is acceptable.
How do I exclude files, not lines?
Use -L to list files that contain no match, or --exclude and --exclude-dir to skip files during a recursive search. -v works on lines inside each file.