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

saf*_*fsd 3 bash shell grep

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

find . -name '*.py' -exec grep -nHr <string> {} \;
Run Code Online (Sandbox Code Playgroud)

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

findpy <string>
Run Code Online (Sandbox Code Playgroud)

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

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

Gor*_*son 10

如果您不想为此创建整个脚本,则只需使用shell函数即可:

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

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


Ide*_*lic 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


Dan*_*nny 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'
Run Code Online (Sandbox Code Playgroud)