How can I pass strings with single quotes to grep?
Solution 1
Single quotes are terminated by single quotes; all other characters in between are preserved exactly as is, including backslashes. Thus there is no way to embed a single quote between single quotes. (But you can end the single quotes, escape a single quote, and start a new set of single quotes, as in 'Single quotes aren'\''t ever really embedded in single quotes.'
)
Suggestion: Avoid find+xargs when grep -r pattern .
can recursively grep on the current directory.
The below commands have equivalent behavior:
grep -rns "add_action('save_post'," .
grep -rns 'add_action('\'save_post\', .
The last command is interpreted as:
'add_action('
->add_action(
\'
->'
save_post
->save_post
\'
->'
,
->,
Concatenating these parts, the grep
command receives the argument add_action('save_post',
.
Solution 2
xargs
expects arguments quoted in some strange way that find
doesn't produce. Never use xargs
in combination with find
, unless you know that your file names don't contain \"'
or whitespace.
Instead of using xargs
, let find
directly call the program you want to run.
find . -exec grep -ns 'add_action('\''save_post'\'',' {} +
With exec … {} +
, the program is invoked once for many files at once, like with xargs
. Some older versions of find
don't support +
here¹, then you have to use ;
instead, which invokes grep
once per file.
You can alternatively use find … -print0 | xargs -0
, if your utilities support it¹. The -print0
option tells find
to emit names separated by a null byte, and -0
tells xargs
to expect null-separated input and not to do any quote interpretation.
Note the quoting above: between single quotes, all characters are interpreted literally, except that '
signifies the end of the literal string. So '\''
is effectively a way of putting a literal single quote inside a single-quoted string; formally, it's “'
end quote, \
literal '
single quote, '
begin quote”.
In the special case of grep
, if your implementation supports it¹, you can dispense with find
and use grep -r
to search inside a directory recursively:
grep -r 'add_action('\''save_post'\'',' .
¹ Linux, Cygwin, FreeBSD and OSX support these features.
Solution 3
grep "add_action('save_post'," ./* -R
You can grep all files in current directory recursively with
-R
option.Search string can be surrounded with
"
.
Related videos on Youtube
Matt
Programs computers. Likes bikes. Plays guitar. Learns languages.
Updated on September 18, 2022Comments
-
Matt over 1 year
My desired outcome is the following: to recursively search a directory looking for a given string in all found files. The following command is my usual port of call:
find ./ | xargs grep -ns 'foobar'
However, when
foobar
has quotes the command fails and gives me a>
prompt in the shell. The specific command that's causing the problem is as follows:find ./ | xargs grep -ns 'add_action(\'save_post\','
I've tried to escape the quotes with backslashes but to no avail. What's the correct way to do this?
-
Matt about 12 yearsgreat insight on the interpretation, thanks!
-
Matt about 12 yearsThanks for the info about
-print0
and-0
, I've looked at these options before but never understood them well enough to actually yield the results I needed. I'll be usinggrep -rns
from now on.