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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/924340/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 20:55:22  来源:igfitidea点击:

How do I write a bash alias/function to grep all files in all subdirectories for a string?

bashshellgrep

提问by saffsd

I've been using the following command to grep for a string in all the python source files in and below my current directory:

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

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

I'd like to simplify things so that I can just type something like

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

findpy <string>

And get the exact same result. Aliases don't seem sufficient since they only do a string expansion, and the argument I need to specify is not the last argument. It sounds like functions are suitable for the task, so I have several questions:

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

  • How do I write it?
  • Where do I put it?
  • 我该怎么写?
  • 我把它放在哪里?

回答by Gordon Davisson

If you don't want to create an entire script for this, you can do it with just a shell function:

如果你不想为此创建整个脚本,你可以只用一个 shell 函数来完成:

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

...but then you may have to define it in both ~/.bashrc and ~/.bash_profile, so it gets defined for both login and interactive shells (see the INVOCATION section of bash's man page).

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

回答by Idelic

All the "find ... -exec" solutions above are OK in the sense that they work, but they are horribly inefficient and will be extremely slow for large trees. The reason is that they launch a new process for everysingle *.py file. Instead, use xargs(1), and run grep only on files (not directories):

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

#! /bin/sh
find . -name \*.py -type f | xargs grep -nHr ""

For example:

例如:

$ 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

回答by Danny

On a side note, you should take a look at Ackfor what you are doing. It is designed as a replacement for Grep written in Perl. Filtering files based on the target language or ignoring .svn directories and the like.

附带说明一下,您应该查看Ack以了解您在做什么。它旨在替代用 Perl 编写的 Grep。根据目标语言过滤文件或忽略 .svn 目录等。

Example (snippet from Trac source):

示例(来自 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'

回答by Shalom Craimer

I wanted something similar, and the answer by Idelicreminded of one of the nice features of xargs: that it puts the command at the end. You see, my problem was that I wanted to write a shell alias that would "accept parameters" (really, that it would expand in such a way to allow me to pass parameter so grep).

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

Here's what I added to my bash_aliases:

这是我添加到我的bash_aliases

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

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

This way, I could write findpy WORDor findpy -e REGEXor findpy -il WORD- the point being that could use any grepcommand-line option.

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

回答by Chas. Owens

Put the following three lines in a file named findpy

将以下三行放在名为的文件中 findpy

#!/bin/bash

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

Then say

然后说

chmod u+x findpy

I normally have a directory called binin my home directory where I put little shell scripts like this. Make sure to add the directory to your PATH.

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

回答by paxdiablo

The script:

剧本:

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

is how I'd do it.

我就是这样做的。

You write it with an editor like vimand put it somewhere on your path. My normal approach is to have a ~/bindirectory and make sure my .profilefile (or equivalent) contains:

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

PATH=$PATH:~/bin

回答by Harold Bamford

Many versions of grep have options to do recursion, specify filename pattern, etc.

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

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

This recurses starting from the current directory (.), looks only at files ending in 'py', uses Perl-style regular expressions.

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

If your version of grep doesn't support --recursive and --include, then you can still use find and xargs, but be sure to allow for pathnames with embedded spaces by using the -print0 argument to find and the --null option to xargs to handle that.

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

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

should work.

应该管用。

回答by Simon Jinyu Liu

Add the following line to your ~/.bashrc or ~/.bash_profile or ~/.profile

将以下行添加到您的 ~/.bashrc 或 ~/.bash_profile 或 ~/.profile

alias findpy='find . -type f -name "*.py" -print0 | xargs -0 grep'

then you can use it like this

然后你可以像这样使用它

findpy def

or with grep options

或使用 grep 选项

findpy -i class

the following alias will ignore the version control meta-directory of git and svn

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

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

回答by MadangLighthouse

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

alias _ff='findfile'