494

I want to grep for the string that starts with a dash/hyphen, like -X, in a file, but it's confusing this as a command line argument.

I've tried:

grep "-X"
grep \-X
grep '-X'
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mike
  • 58,961
  • 76
  • 175
  • 221

12 Answers12

657

Use:

grep -- -X

Documentation

Related: What does a bare double dash mean? (thanks to nutty about natty).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
newacct
  • 119,665
  • 29
  • 163
  • 224
  • 78
    for those of us wondering at this stage what `--` means or does: http://unix.stackexchange.com/questions/11376/what-does-double-dash-mean – nutty about natty Apr 01 '13 at 09:45
  • 2
    Works with The Silver Searcher (ag) as well. – Zev Eisenberg Jun 19 '13 at 03:37
  • If you want to use with variable having spaces you should use something like this: `ARGS="-a -b -c"` `grep -- "$ARGS"` – zapstar Dec 16 '14 at 15:48
  • 3
    @zapstar Or just, `grep -- "--name awesome"`. – Brett Widmeier Nov 23 '15 at 17:40
  • What if I want to grep for `-X` followed by a space? (or a new line) – pkaramol Jan 20 '18 at 18:43
  • Example: I want to do a case-insensitive (`-i`) search for `-std=` in my git repo. The following works: `git grep -ni -- -std=` – Gabriel Staples Feb 05 '19 at 01:30
  • grep -r <-other-options> -- "-X " ./ ..anything within quotes immediately *after* the -- (including spaces) will be considered part of the search string. If you put options *before* the -- then you can put as many options as you want, such as -r, etc. – emery Feb 08 '21 at 16:49
74

The dash is a special character in Bash as noted at http://tldp.org/LDP/abs/html/special-chars.html#DASHREF. So escaping this once just gets you past Bash, but Grep still has it's own meaning to dashes (by providing options).

So you really need to escape it twice (if you prefer not to use the other mentioned answers). The following will/should work

grep \\-X
grep '\-X'
grep "\-X"

One way to try out how Bash passes arguments to a script/program is to create a .sh script that just echos all the arguments. I use a script called echo-args.sh to play with from time to time, all it contains is:

echo $*

I invoke it as:

bash echo-args.sh \-X
bash echo-args.sh \\-X
bash echo-args.sh "\-X"

You get the idea.

codeforester
  • 39,467
  • 16
  • 112
  • 140
Chad Gorshing
  • 2,998
  • 32
  • 30
  • 4
    I don't think - is a special character in Bash despite what the ABS guide says. Bash doesn't process arguments beginning with - any differently than others. The command or built-in that Bash subsequently calls will handle arguments beginning with a dash however it sees fit. Most of the Bash built-ins and Linux and GNU commands handle -- as an option terminator. Use 'set -x' to see the commands and arguments that Bash uses before they will be executed, but after Bash has expanded escapes, globs, and braces. Grep is a confusing example because it does its own handling of backslash escapes. – Noah Spurrier Oct 09 '19 at 10:21
  • How can an answer that is so plain wrong get so many upvotes? – André Chalella Jun 16 '23 at 22:13
39

With GNU grep, grep -e -X will do the trick.

Thomas
  • 174,939
  • 50
  • 355
  • 478
  • 1
    my grep doesn't have -e, very weird – Mike Mar 11 '10 at 19:20
  • 2
    Available on solaris from /usr/xpg4/bin/grep, btw. Lots of more-complete utilities in that directory. – pra Mar 12 '10 at 17:02
  • It worked under MinGW ([MinGW](http://en.wikipedia.org/wiki/MinGW) doesn't support `-P` (but that is another story and does not apply here)). – Peter Mortensen Apr 11 '17 at 18:34
  • >[What if a pattern has a leading ‘-’? `grep -e '--cut here--' *` searches for all lines matching `‘--cut here--’`. Without -e, grep would attempt to parse `‘--cut here--’` as a list of options.](https://www.gnu.org/software/grep/manual/grep.html) – phuclv Dec 01 '17 at 08:59
  • This answer should be the accepted one since it allows putting a list of filenames to search into after the pattern. The double dash variant only works with a stream from standard input. – Johan Boulé May 20 '23 at 03:51
  • This is correct. `man grep` says about `-e`: "This option can be used to protect a pattern beginning with “-”. – André Chalella Jun 16 '23 at 22:14
33
grep -- -X
grep \\-X
grep '\-X'
grep "\-X"
grep -e -X
grep [-]X
wisbucky
  • 33,218
  • 10
  • 150
  • 101
John Henry
  • 2,419
  • 2
  • 20
  • 22
8

I dont have access to a Solaris machine, but grep "\-X" works for me on linux.

ezpz
  • 11,767
  • 6
  • 38
  • 39
6

The correct way would be to use "--" to stop processing arguments, as already mentioned. This is due to the usage of getopt_long (GNU C-function from getopt.h) in the source of the tool.

This is why you notice the same phenomena on other command-line tools; since most of them are GNU tools, and use this call,they exhibit the same behavior.

As a side note - getopt_long is what gives us the cool choice between -rlo and --really_long_option and the combination of arguments in the interpreter.

fmmarques
  • 301
  • 3
  • 3
5

If you're using another utility that passes a single argument to grep, you can use:

'[-]X'
Colin vH
  • 527
  • 3
  • 9
2

you can use nawk

$ nawk '/-X/{print}' file
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
0

None of the answers not helped me (ubuntu 20.04 LTS).
I found a bit another option:

My case:

systemctl --help | grep -w -- --user

-w will match a whole word.
-- means end of command arguments (to mark -w as not part of the grep command)

Давид Шико
  • 362
  • 1
  • 4
  • 13
0

On macOS/BSD:

grep -e "-X"

is enough.

ocodo
  • 29,401
  • 18
  • 105
  • 117
-1

grep "^-X" file

It will grep and pick all the lines form the file. ^ in the grep"^" indicates a line starting with

sasank
  • 1
-3
ls -l | grep "^-"

Hope this one would serve your purpose.

Pang
  • 9,564
  • 146
  • 81
  • 122
XINU
  • 3
  • 1
  • 2
    This expression catch only lines that begin with a dash. It does not complies with the initial question. He want to search for a string starting by a dash but the lines that contains this string did not necessary begin with a dash.In the initial question, the string beginning with a dash can be anywhere in the line. – Laurent Simon Feb 20 '17 at 15:52