Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何编写bash别名/函数以grep所有子目录中的所有文件作为字符串?_Bash_Shell_Grep - Fatal编程技术网

如何编写bash别名/函数以grep所有子目录中的所有文件作为字符串?

如何编写bash别名/函数以grep所有子目录中的所有文件作为字符串?,bash,shell,grep,Bash,Shell,Grep,我一直在使用以下命令在我当前目录下的所有python源文件中grep查找字符串: find . -name '*.py' -exec grep -nHr <string> {} \; 我想把事情简化,这样我就可以键入 findpy <string> 得到完全相同的结果。别名似乎不够,因为它们只进行字符串扩展,而且我需要指定的参数不是最后一个参数。听起来函数适合此任务,因此我有几个问题: 我该怎么写呢? 我应该把它放在哪里? 将以下三行放入名为findpy的文件中 然后

我一直在使用以下命令在我当前目录下的所有python源文件中grep查找字符串:

find . -name '*.py' -exec grep -nHr <string> {} \;
我想把事情简化,这样我就可以键入

findpy <string>
得到完全相同的结果。别名似乎不够,因为它们只进行字符串扩展,而且我需要指定的参数不是最后一个参数。听起来函数适合此任务,因此我有几个问题:

我该怎么写呢? 我应该把它放在哪里?
将以下三行放入名为findpy的文件中

然后说

chmod u+x findpy
我通常在我的主目录中有一个名为bin的目录,在那里我放置了像这样的小shell脚本。确保将目录添加到路径中。

脚本:

#!/bin/bash
find . -name '*.py' -exec grep -nHr "$1" {} ';'
我会这么做的

您可以使用vim之类的编辑器编写它,并将其放在您的路径上的某个位置。我通常的做法是使用~/bin目录,并确保我的.profile文件或等效文件包含:

PATH=$PATH:~/bin

如果您不想为此创建一个完整的脚本,可以只使用一个shell函数:

findpy() { find . -name '*.py' -exec grep -nHr "$1" {} \; ; }

…但是,您可能需要在~/.bashrc和~/.bash_配置文件中定义它,以便为登录shell和交互式shell定义它。请参阅bash手册页的调用部分。

所有查找-上面的exec解决方案在工作的意义上是可以的,但是它们的效率非常低,对于大型树来说速度非常慢。原因是他们为每个*.py文件启动了一个新进程。相反,请使用xargs1,并仅对文件而不是目录运行grep:

#! /bin/sh find . -name \*.py -type f | xargs grep -nHr "$1" 例如:

$ time sh -c 'find . -name \*.cpp -type f -exec grep foo {} \; >/dev/null' real 0m3.747s $ time sh -c 'find . -name \*.cpp -type f | xargs grep foo >/dev/null' real 0m0.278s
另一方面,你应该看看你在做什么。它是作为用Perl编写的Grep的替代品而设计的。基于目标语言筛选文件或忽略.svn目录等

来自Trac源的示例代码段:

$ ack --python foo ./mysource
ticket/tests/wikisyntax.py
139:milestone:foo
144:<a class="missing milestone" href="/milestone/foo" rel="nofollow">milestone:foo</a>

ticket/tests/conversion.py
34:        ticket['foo'] = 'This is a custom field'

ticket/query.py
239:        count_sql = 'SELECT COUNT(*) FROM (' + sql + ') AS foo'

许多版本的grep都有递归、指定文件名模式等选项

grep --perl-regexp --recursive --include='*.py' --regexp="$1" .
它从当前目录开始递归,只查看以“py”结尾的文件,使用Perl样式的正则表达式

如果您的grep版本不支持-recursive和-include,那么您仍然可以使用find和xargs,但是请确保允许使用带有嵌入空格的路径名,方法是使用-print0参数进行查找,使用xargs的-null选项进行处理

find . -type f -name '*.py' -print0 | xargs --null grep "$1"

应该可以工作。

我想要类似的东西,并且提醒您xargs的一个很好的特性:它将命令放在末尾。你们看,我的问题是,我想写一个shell别名,它将真正接受参数,它将以这样一种方式扩展,允许我将参数传递到grep

以下是我在bash_别名中添加的内容:

别名findpy=find-类型f-名称'*.py'| xargs grep


通过这种方式,我可以编写findpy-WORD或findpy-e REGEX或findpy-il-WORD,重点是可以使用任何grep命令行选项。

将以下行添加到~/.bashrc或~/.bash_配置文件或~/.profile中

#######################################################################################
#
# Function to search all files (including sub-directories) that match a given file
# extension ($2) looking for an indicated string ($1) - in a case insensitive manner.
#
# For Example:
#
# -> findfile AllowNegativePayments cpp
#
#
#######################################################################################
findfile ()
{
    find . -iname "*.$2*" -type f -print0 | xargs -0 grep -i "$1" {} \; 2> /dev/nul
}

alias _ff='findfile'
alias findpy='find . -type f -name "*.py" -print0 | xargs -0 grep'
那么你可以这样使用它

findpy def
或者使用grep选项

findpy -i class
以下别名将忽略git和svn的版本控制元目录

alias findpy='find . -type f -not -path "*/.git/*" -a -not -path "*/.svn/*" -name "*.py" -print0 | xargs -0 grep'

我认为你不需要在grep上加-r-我的发行版已经设置了.bash_配置文件所采取的唯一操作是source.bashrc,所以这不是问题。谢谢函数和别名应该放在~/.bashrc和~/.bash_profile中,或者~/.profile应该是源代码~/.bashrcYah,从另一个源代码中找到一个会使工作更轻松。为了安全起见,我首先要检查.bash_配置文件,如下所示:if[-f~/.bashrc];那么~/。巴什尔委员会;时间是如何找到的-name*.cpp-type f-exec grep foo{}+>/dev/null'比较?对我来说,它比xargs快一点,但是xargs在一些名称中带有空格的Python文件上没有给出这样的文件或目录错误,这要感谢cmu。-exec版本没有抱怨。使用-exec…+在性能方面应该与xargs相当,但它不可移植,也不像xargs那样灵活。文件名中的空格可以通过将-print0传递给find和-0传递给args来轻松处理,因此文件名由NUL字符而不是空格分隔,即find-name*.cpp-print0 | xargs-0 grep foo。实际上,我刚刚检查了-exec…+在POSIX中,因此可以认为是可移植的。这只剩下灵活性作为xargs的参数:-我发现包含“:”字符的外来文件名存在一些问题。将其更改为:find-在我的系统上键入f-name*.py-print0 | xargs-null grep-nHr$1,find比grep-recursive更快。此外,grep-recursive在某些情况下返回递归目录循环错误,因为find不有趣!我从来没有得到递归目录循环,因为我通常在没有真正符号链接的Windows框上运行。我想这就是你犯错误的原因吧?
alias findpy='find . -type f -not -path "*/.git/*" -a -not -path "*/.svn/*" -name "*.py" -print0 | xargs -0 grep'