3

我一直在使用以下命令在当前目录及其下方的所有 python 源文件中对字符串进行 grep:

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

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

findpy <string>

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

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

9 回答 9

10

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

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

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

于 2009-05-29T05:30:23.737 回答
6

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

#!/bin/sh
寻找 。-name \*.py -type f | xargs grep -nHr "$1"

例如:

$ 时间 sh -c '查找 . -name \*.cpp -type f -exec grep foo {} \; >/开发/空'
实际0m3.747s
$ 时间 sh -c '查找 . -name \*.cpp -type f | xargs grep foo >/dev/null'
实际0m0.278s
于 2009-05-29T05:46:33.330 回答
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'
于 2009-05-29T18:19:44.873 回答
2

我想要类似的东西,Idelic 的回答让我想起了 : 的一个很好的特性xargs:它将命令放在最后。你看,我的问题是我想编写一个“接受参数”的 shell 别名(实际上,它会以这样的方式扩展以允许我传递参数 so grep)。

这是我添加到我的bash_aliases

别名 findpy="find . -type f -name '*.py' | xargs grep"

这样,我可以写findpy WORDor findpy -e REGEXor findpy -il WORD- 关键是可以使用任何grep命令行选项。

于 2013-06-13T05:38:34.773 回答
1

将以下三行放在一个名为findpy

#!/bin/bash

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

然后说

chmod u+x findpy

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

于 2009-05-29T04:09:07.437 回答
1

剧本:

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

我会怎么做。

你用一个编辑器写它,vim然后把它放在你的路径上。我通常的方法是有一个~/bin目录并确保我的.profile文件(或等效文件)包含:

PATH=$PATH:~/bin
于 2009-05-29T04:12:45.523 回答
1

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

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

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

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

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

应该管用。

于 2009-05-30T00:06:30.773 回答
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'
于 2013-09-25T06:47:50.137 回答
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'
于 2013-07-22T01:52:13.140 回答