在一组文件中查找文本的更简洁方法是什么?

时间:2021-05-31 23:37:01

I currently use the following command, but it's a little unwieldy to type. What's a shorter alternative?

我目前使用以下命令,但输入有点笨拙。什么是更短的选择?

find . -name '*.txt' -exec grep 'sometext' '{}' \; -print

Here are my requirements:

这是我的要求:

  • limit to a file extension (I use SVN and don't want to be searching through all those .svn directories)
  • 限制文件扩展名(我使用SVN,不想搜索所有这些.svn目录)

  • can default to the current directory, but it's nice to be able to specify a different directory
  • 可以默认为当前目录,但能够指定不同的目录是很好的

  • must be recursive
  • 必须是递归的

UPDATE: Here's my best solution so far:

更新:到目前为止,这是我最好的解决方案:

grep -r 'sometext' * --include='*.txt'

UPDATE #2: After using grep for a bit, I realized that I like the output of my first method better. So, I followed the suggestions of several responders and simply made a shell script and now I call that with two parameters (extension and text to find).

更新#2:在使用grep之后,我意识到我更喜欢第一种方法的输出。所以,我按照几个响应者的建议,简单地制作了一个shell脚本,现在我用两个参数(扩展名和要查找的文本)调用它。

9 个解决方案

#1


9  

grep has -r (recursive) and --include (to search only in files and directories matching a pattern).

grep具有-r(递归)和--include(仅搜索与模式匹配的文件和目录)。

#2


3  

If its too unweildy, write a script that does it and put it in your personal bin directory. I have a 'fif' script which searches source files for text, basically just doing a single find like you have here:

如果它太不合适,请编写一个执行此操作的脚本并将其放入您的个人bin目录中。我有一个'fif'脚本搜索源文件中的文本,基本上只是像你在这里做一个查找:

#!/bin/bash

set -f  # disable pathname expansion

pattern="-iname *.[chsyl] -o -iname *.[ch]pp -o -iname *.hh -o -iname *.cc
-o -iname *.java -o -iname *.inl"
prune=""
moreargs=true
while $moreargs && [ $# -gt 0 ]; do
    case $1 in
    -h)
        pattern="-iname *.h -o -iname *.hpp -o -iname *.hh"
        shift
        ;;
    -prune)
        prune="-name $2 -prune -false -o $prune"
        shift
        shift
        ;;
    *)
        moreargs=false;
        ;;
    esac
done

find . $prune $pattern | sed 's/ /\\ /g' | xargs grep "$@"

it started life as a single-line script and got features added over the years as I needed them.

它起源于单行脚本,并且在我需要的时候添加了多年来添加的功能。

#3


3  

This is much more efficient since it invokes grep many fewer times, though it's hard to say it's more succinct:

这样效率要高得多,因为它调用grep的次数要少很多,尽管很难说它更简洁:

find . -name '*.txt' -print0 | xargs -0 grep 'sometext' /dev/null

Notes:

/find -print0 and xargs -0 makes pathnames with embedded blanks work correctly.

/ find -print0和xargs -0使具有嵌入空格的路径名正常工作。

The /dev/null argument makes sure grep always prepends a filename.

/ dev / null参数确保grep始终包含文件名。

#4


3  

Install ack and use

安装确认并使用

ack -aG'\.txt$' 'sometext'

#5


3  

I second ephemient's suggestion of ack. I'm writing this post to highlight a particular issue.

我第二次提出了ack的建议。我写这篇文章是为了突出一个特定的问题。

In response to jgormley (in the comments): ack is available as a single file which will work wherever the right Perl version is installed (which is everywhere).

回应jgormley(在评论中):ack作为单个文件提供,可以在安装了正确的Perl版本的任何地方使用(无处不在)。

Given that on non-Linux platforms grep regularly does not accept -R, arguably using ack is more portable.

鉴于在非Linux平台上,grep经常不接受-R,可以说使用ack更具可移植性。

#6


2  

I use zsh, which has recursive globbing. If you needed to look at specific filetypes, the following would be equivalent to your example:

我使用zsh,它有递归的globbing。如果您需要查看特定的文件类型,以下内容将等同于您的示例:

grep 'sometext' **/*.txt

If you don't care about the filetype, the -r option will be better:

如果你不关心文件类型,-r选项会更好:

grep -r 'sometext' *

Although, A minor tweak to your original example will give you exactly what you want:

虽然,对原始示例的一个小调整将为您提供您想要的内容:

find . -name '*.txt' \! -wholename '*/.svn/*' -exec grep 'sometext' '{}' \; -print

If this is something you do frequently, make it a function (put this in your shell config):

如果你经常这样做,那就把它变成一个函数(把它放在你的shell配置中):

function grep_no_svn {
    find . -name "${2:-*}" \! -wholename '*/.svn/*' -exec grep "$1" '{}' \; -print
}

Where the first argument to the function is the text you're searching for. So:

函数的第一个参数是您要搜索的文本。所以:

$ grep_here_no_svn "sometext"

Or:

$ grep_here_no_svn "sometext" "*.txt"

#7


1  

You could write a script (in bash or whatever -- I have one in Groovy) and place it on the path. E.g.

你可以写一个脚本(用bash或其他什么 - 我在Groovy中有一个)并将它放在路径上。例如。

$ myFind.sh txt targetString

where myFind.sh is:

myFind.sh在哪里:

find . -name "*.$1" -exec grep $2 {} \; -print

#8


0  

I usualy avoid the "man find" by using grep $(find . -name "*,txt")

我通常使用grep $(find。-name“*,txt”)来避免“man find”

#9


0  

You say that you like the output of your method (using find) better. The only difference I can see between them is that grepping multiple files will put the filename on the front.

你说你更喜欢你的方法的输出(使用find)。我可以在它们之间看到的唯一区别是,grepping多个文件会将文件名放在前面。

You can always (in GNU grep, but you must be using that or -r and --include wouldn't work) turn the filename off by using -h (--no-filename). The opposite, for anyone who does want filenames but has to use find for some other reason, is -H (--with-filename).

你可以随时(在GNU grep中,但你必须使用它或-r并且--include不起作用)通过使用-h( - no-filename)关闭文件名。相反,对于任何想要文件名但由于某些其他原因必须使用find的人来说,是-H( - with-filename)。

#1


9  

grep has -r (recursive) and --include (to search only in files and directories matching a pattern).

grep具有-r(递归)和--include(仅搜索与模式匹配的文件和目录)。

#2


3  

If its too unweildy, write a script that does it and put it in your personal bin directory. I have a 'fif' script which searches source files for text, basically just doing a single find like you have here:

如果它太不合适,请编写一个执行此操作的脚本并将其放入您的个人bin目录中。我有一个'fif'脚本搜索源文件中的文本,基本上只是像你在这里做一个查找:

#!/bin/bash

set -f  # disable pathname expansion

pattern="-iname *.[chsyl] -o -iname *.[ch]pp -o -iname *.hh -o -iname *.cc
-o -iname *.java -o -iname *.inl"
prune=""
moreargs=true
while $moreargs && [ $# -gt 0 ]; do
    case $1 in
    -h)
        pattern="-iname *.h -o -iname *.hpp -o -iname *.hh"
        shift
        ;;
    -prune)
        prune="-name $2 -prune -false -o $prune"
        shift
        shift
        ;;
    *)
        moreargs=false;
        ;;
    esac
done

find . $prune $pattern | sed 's/ /\\ /g' | xargs grep "$@"

it started life as a single-line script and got features added over the years as I needed them.

它起源于单行脚本,并且在我需要的时候添加了多年来添加的功能。

#3


3  

This is much more efficient since it invokes grep many fewer times, though it's hard to say it's more succinct:

这样效率要高得多,因为它调用grep的次数要少很多,尽管很难说它更简洁:

find . -name '*.txt' -print0 | xargs -0 grep 'sometext' /dev/null

Notes:

/find -print0 and xargs -0 makes pathnames with embedded blanks work correctly.

/ find -print0和xargs -0使具有嵌入空格的路径名正常工作。

The /dev/null argument makes sure grep always prepends a filename.

/ dev / null参数确保grep始终包含文件名。

#4


3  

Install ack and use

安装确认并使用

ack -aG'\.txt$' 'sometext'

#5


3  

I second ephemient's suggestion of ack. I'm writing this post to highlight a particular issue.

我第二次提出了ack的建议。我写这篇文章是为了突出一个特定的问题。

In response to jgormley (in the comments): ack is available as a single file which will work wherever the right Perl version is installed (which is everywhere).

回应jgormley(在评论中):ack作为单个文件提供,可以在安装了正确的Perl版本的任何地方使用(无处不在)。

Given that on non-Linux platforms grep regularly does not accept -R, arguably using ack is more portable.

鉴于在非Linux平台上,grep经常不接受-R,可以说使用ack更具可移植性。

#6


2  

I use zsh, which has recursive globbing. If you needed to look at specific filetypes, the following would be equivalent to your example:

我使用zsh,它有递归的globbing。如果您需要查看特定的文件类型,以下内容将等同于您的示例:

grep 'sometext' **/*.txt

If you don't care about the filetype, the -r option will be better:

如果你不关心文件类型,-r选项会更好:

grep -r 'sometext' *

Although, A minor tweak to your original example will give you exactly what you want:

虽然,对原始示例的一个小调整将为您提供您想要的内容:

find . -name '*.txt' \! -wholename '*/.svn/*' -exec grep 'sometext' '{}' \; -print

If this is something you do frequently, make it a function (put this in your shell config):

如果你经常这样做,那就把它变成一个函数(把它放在你的shell配置中):

function grep_no_svn {
    find . -name "${2:-*}" \! -wholename '*/.svn/*' -exec grep "$1" '{}' \; -print
}

Where the first argument to the function is the text you're searching for. So:

函数的第一个参数是您要搜索的文本。所以:

$ grep_here_no_svn "sometext"

Or:

$ grep_here_no_svn "sometext" "*.txt"

#7


1  

You could write a script (in bash or whatever -- I have one in Groovy) and place it on the path. E.g.

你可以写一个脚本(用bash或其他什么 - 我在Groovy中有一个)并将它放在路径上。例如。

$ myFind.sh txt targetString

where myFind.sh is:

myFind.sh在哪里:

find . -name "*.$1" -exec grep $2 {} \; -print

#8


0  

I usualy avoid the "man find" by using grep $(find . -name "*,txt")

我通常使用grep $(find。-name“*,txt”)来避免“man find”

#9


0  

You say that you like the output of your method (using find) better. The only difference I can see between them is that grepping multiple files will put the filename on the front.

你说你更喜欢你的方法的输出(使用find)。我可以在它们之间看到的唯一区别是,grepping多个文件会将文件名放在前面。

You can always (in GNU grep, but you must be using that or -r and --include wouldn't work) turn the filename off by using -h (--no-filename). The opposite, for anyone who does want filenames but has to use find for some other reason, is -H (--with-filename).

你可以随时(在GNU grep中,但你必须使用它或-r并且--include不起作用)通过使用-h( - no-filename)关闭文件名。相反,对于任何想要文件名但由于某些其他原因必须使用find的人来说,是-H( - with-filename)。