I often run commands like this:
find … -exec grep … --color=always -l {} \+
and sometimes I need to open the matching files in Vim.
But what is the most reliable way to do so?
One way seems to be
vim $(find … -exec grep … {} \+)
Another way seems to make use of xargs
.
Are there advantages/disvantages/concerns to be aware for these two, and others, if any, methods?
Best Answer
is an unquoted command substitution, so word splitting will be performed on whitespace on its result, as well as pathname expansion. I.e., if a file
a b
matches, Vim will incorrectly opena
andb
. If a file*
matches, alas, that will be expanded to every file in the corresponding directory. An appropriate solution isGrep runs in
q
uiet mode: Only its return value is used for each file. If0
, a match was found in that file and the file is passed on to Vim.{} \;
means one file will be analysed at a time by Grep. If we used{} +
, all files would be passed as arguments to Grep, and a found match in any of those files would result on0
exit status, so all those files would be opened in Vim. On the other hand,{} +
is used for Vim so that it each found file goes to one buffer in a single Vim process. You can try changing them to feel the difference.If you need to speed things up:
If
'pattern'
is not a regular expression, but only a fixed pattern, add the-F
flag to Grep.grep -lZ
, Xargs and special shell constructs should also speed-up the process if you have those available, see Stéphane Chazelas' answer.And here are another similar use cases with Xargs, Find and Vim.