如何编写一个bash别名/函数来grep所有子目录中的所有文件?

时间:2009-05-29 04:05:43

标签: bash shell grep

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

find . -name '*.py' -exec grep -nHr <string> {} \;

我想简化一些事情,这样我就可以输入类似

的内容
findpy <string>

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

  • 我该怎么写呢?
  • 我把它放在哪里?

9 个答案:

答案 0 :(得分:10)

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

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

...但是你可能必须在〜/ .bashrc和〜/ .bash_profile中定义它,因此它为登录和交互式shell定义(参见bash手册页的INVOCATION部分)。

答案 1 :(得分:6)

上面的所有“find ... -exec”解决方案在它们工作的意义上都是可以的,但是它们非常低效,并且对于大树来说会非常慢。原因是他们为 每个 单个* .py文件启动了一个新流程。相反,使用xargs(1),并仅对文件(而不是目录)运行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

答案 2 :(得分:6)

另一方面,你应该看看Ack你在做什么。它被设计为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'

答案 3 :(得分:2)

我想要类似的东西,而answer by Idelic提醒了xargs的一个很好的功能:它将命令放在最后。你看,我的问题是我想编写一个“接受参数”的shell别名(实际上,它会以这种方式扩展,允许我传递参数grep)。

以下是我添加到bash_aliases的内容:

alias findpy =“find.-type f -name'* .py'| xargs grep”

这样,我可以编写findpy WORDfindpy -e REGEXfindpy -il WORD - 可以使用任何grep命令行选项。

答案 4 :(得分:1)

将以下三行放在名为findpy

的文件中
#!/bin/bash

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

然后说

chmod u+x findpy

我的主目录中通常有一个名为bin的目录,我在其中放置了这样的小shell脚本。请务必将目录添加到PATH

答案 5 :(得分:1)

剧本:

#!/bin/bash
find . -name '*.py' -exec grep -nHr "$1" {} ';'

我是怎么做的。

您可以使用vim这样的编辑器编写它并将其放在您的路径上。我的正常方法是拥有一个~/bin目录,并确保我的.profile文件(或等效文件)包含:

PATH=$PATH:~/bin

答案 6 :(得分:1)

许多版本的grep都有选项来进行递归,指定文件名模式等等。

grep --perl-regexp --recursive --include='*.py' --regexp="$1" .

这个从当前目录(。)开始递归,只查看以'py'结尾的文件,使用Perl风格的正则表达式。

如果您的grep版本不支持--recursive和--include,那么您仍然可以使用find和xargs,但请确保通过使用-print0参数来查找包含嵌入空格的路径名,并且 - -null选项让xargs处理它。

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

应该有用。

答案 7 :(得分:1)

将以下行添加到〜/ .bashrc或〜/ .bash_profile或〜/ .profile

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'

答案 8 :(得分:0)

#######################################################################################
#
# 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'