我一直在使用以下命令来grep查找当前目录中和下面的所有python源文件中的字符串:
find . -name '*.py' -exec grep -nHr <string> {} \;
我想简化一些事情,这样我就可以输入类似
的内容findpy <string>
得到完全相同的结果。别名似乎不够,因为它们只进行字符串扩展,而我需要指定的参数不是最后一个参数。听起来函数适合于任务,所以我有几个问题:
答案 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 WORD
或findpy -e REGEX
或findpy -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'