Today I was searching for --debug in a log file.
So, I ran grep "--debug" file.log.
To my utter surprise, instead of seeing a match, I got this error:
grep: unrecognized option '--debug'
Usage: grep [OPTION]... PATTERNS [FILE]...
I didn’t expect to see any error because I had quoted the pattern ("--debug").
After few minutes of searching, I found the fix:
grep -- --debug file.logThis is where the humble double hyphen -- steps in.
In simple words, it tells grep:
“Stop treating anything after this as an option. From here on, everything is data (either a pattern or a filename).”
This concept is officially called an end-of-options marker.
What -- means (technical definition)
In POSIX command-line utilities, -- is an argument delimiter that signals the end of all command options. After --, the utility must treat the following tokens strictly as operands, not flags.
According to POSIX.1-2017 (The Open Group Base Specifications)1 :
The first -- argument that is not an option-argument should be accepted as a delimiter indicating the end of options. Any following arguments should be treated as operands, even if they begin with the ‘-’ character.
In the context of grep:
- Before
--: arguments can be interpreted as options (-i,-R,-v, etc.) - After
--: arguments are treated as patterns or file operands, even if they start with a hyphen.
Why do you need --?
Because many real-world patterns and filenames begin with a hyphen:
- Searching for a value like
-v,-p, or--help - Searching for negative numbers:
-10,-999 - Searching for strings containing dashes:
--foo,---
Without an end-of-options marker, grep thinks you’re passing flags.
For, example in the following:
grep -v file.txtgrep interprets -v as the “invert match” option, not a pattern.
Using -- fixes it:
grep -- -v file.txtNow grep searches for the literal string -v.
Another use case: searching for system accounts
In the /etc/shadow file, system accounts typically have an asterisk (*) character in place of the password field. One way to find such accounts is:
sudo cat /etc/shadow | grep -- "*"You can try running sudo cat /etc/shadow | grep * - to see grep failing.
Summary
The end-of-options marker -- can be used in grep to treat everything after it as literal input.
