当一组文件中的某些文件包含空格时,如何搜索字符串?

当一组文件中的某些文件包含空格时,如何搜索字符串?

我正在运行 Mac 10.7.5。在终端中,我将使用此命令查找包含字符串的文件

find src/main -name "*" | xargs grep -i 'mystring'

但是当文件包含空格时,我会得到如下结果

grep: images/mystuff/essential-questions-selected-arrow-ela: No such file or directory
grep: 5.24.38: No such file or directory
grep: PM.png: No such file or directory

上述示例中的实际文件是“essential-questions-selected-arrow-ela 5.24.38 PM.png”即使被搜索的文件包含空格,我该如何成功运行上述命令?

答案1

如果你想使用find输出xargs推荐的方法是使用NUL字符来分隔每个文件名:

find src/main -name "*" -print0 | xargs -0 grep -i 'mystring'

原因是 shell(xargs特别是)通常分裂论点(或在 的情况下为 输入xargs)基于空白,即空格、制表符和换行符。一旦使用-0xargs将读取由 分隔的每个字段NUL,这就是输出find -print0

这将在 GNUfind以及xargsOS X 中包含的版本中起作用。其他版本可能没有这些选项,因为它们不是 POSIX 所要求的。


但话又说回来,这其实不是必要的。"*"名称模式扩展到所有可能的名称。grep可以自行递归,因此所需的只是:

grep -ri 'mystring' src/main

在 Bash 4 中(默认情况下不随 OS X 一起提供),您还可以执行递归遍历,例如遍历所有.txt文件,使用选项globstar

shopt -s globstar
grep -i 'mystring' **/*.txt

答案2

到目前为止,执行此类操作最安全、最简单的方法是使用 find 的-exec选项。来自man find

-exec utility [argument ...] ;
     True if the program named utility returns a zero value as its exit status.
     Optional arguments may be passed to the utility.  The expression must be 
     terminated by a semicolon (``;'').  If you invoke find from a shell you 
     may need to quote the semicolon if the shell would otherwise treat it as a 
     control operator.  If the string ``{}'' appears anywhere in the utility 
     name or the arguments it is replaced by the pathname of the current file.  
     Utility will be executed from the directory from which find was executed.  
     Utility and arguments are not subject to the further expansion of shell 
     patterns and constructs.

-exec utility [argument ...] {} +
     Same as -exec, except that ``{}'' is replaced with as many pathnames as 
     possible for each invo-cation invocationcation of utility. This behaviour 
     is similar to that of xargs(1).

换句话说,该-exec选项将根据 find 的结果运行您提供的任何内容,替换{}找到的每个文件(或目录)。因此,要 grep 特定字符串,您可以执行以下操作:

find src/main -name "*" -exec grep -i 'mystring' {} +

但是,这样也会找到目录并给出错误。请注意,它会起作用,当您尝试在目录上运行它时,它只会发出抱怨,使用 也会遇到同样的问题xargs。您实际上在这里尝试做的是查找所有文件并且只查找文件。在这种情况下,不需要 ,-name '*'因为find src/main和 完全相同find src/main -name "*"。因此,不要使用它,而是指定您只想查找文件:

find src/main -type f -exec grep -i 'mystring' {} +

相关内容