Answers:
我知道这是一个旧线程,但是我偶然发现了它,并认为我会分享我的方法,我发现这是一种非常快速的方法,可find
用于仅查找非二进制文件:
find . -type f -exec grep -Iq . {} \; -print
-I
grep 的选项告诉它立即忽略二进制文件,而.
连同的选项-q
会使它立即与文本文件匹配,因此运行非常快。如果您担心空格,可以将其更改-print
为-print0
用于管道到xargs -0
或之类的东西(感谢小费,@ lucas.werkmeister!)
同样,仅对于某些BSD版本(find
例如OS X)而言,第一个点才是必需的,但是如果您希望始终将其放置在别名或其他内容中,那么仅将其始终存在并不会带来任何伤害。
编辑:正如@ruslan正确指出的那样,-and
可以隐式地将其省略。
find -type f -exec grep -Iq . {} \; -and -print
which将文件保留在其中的优点find
;您可以-print
用-exec
只为文本文件运行的另一个替换。(如果让您grep
打印文件名,则将无法使用换行符来区分文件名。)
find . -type f -exec grep -Il . {} +
快得多。缺点是它不能-exec
像@ lucas.werkmeister所建议的那样被其他人扩展
为什么不方便?如果您需要经常使用它,并且不想每次都键入它,只需为其定义一个bash函数:
function findTextInAsciiFiles {
# usage: findTextInAsciiFiles DIRECTORY NEEDLE_TEXT
find "$1" -type f -exec grep -l "$2" {} \; -exec file {} \; | grep text
}
把它放在你的.bashrc
然后运行:
findTextInAsciiFiles your_folder "needle text"
无论你什么时候想要。
编辑以反映OP的编辑:
如果您想删除mime信息,则可以在筛选出mime信息的管道中再添加一个阶段。这应该做的伎俩,通过采取只什么来之前:
:cut -d':' -f1
:
function findTextInAsciiFiles {
# usage: findTextInAsciiFiles DIRECTORY NEEDLE_TEXT
find "$1" -type f -exec grep -l "$2" {} \; -exec file {} \; | grep text | cut -d ':' -f1
}
file
手册:“用户依赖于知道目录中所有可读文件都印有'文本'一词。”
/proc/meminfo
,/proc/cpuinfo
等是文本文件,但file /proc/meminfo
说/proc/meminfo: empty
。我想知道是否除了“文本”之外还应该测试“空”,但是不确定是否其他类型也可以报告“空”。
find . -type f -print0 | xargs -0 file | grep -P text | cut -d: -f1 | xargs grep -Pil "search"
不幸的是,这不能节省空间。将其放入bash脚本会使它变得更容易。
这是空间安全的:
#!/bin/bash
#if [ ! "$1" ] ; then
echo "Usage: $0 <search>";
exit
fi
find . -type f -print0 \
| xargs -0 file \
| grep -P text \
| cut -d: -f1 \
| xargs -i% grep -Pil "$1" "%"
text.bin
怎么办?2.如果文件名包含一个字符:
怎么办?
这个怎么样:
$ grep -rl "needle text" my_folder | tr '\n' '\0' | xargs -r -0 file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable'
如果您想要不带文件类型的文件名,只需添加最终sed
过滤器即可。
$ grep -rl "needle text" my_folder | tr '\n' '\0' | xargs -r -0 file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable' | sed 's|:[^:]*$||'
您可以通过-e 'type'
在最后一个grep
命令中添加更多选项来过滤掉不需要的文件类型。
编辑:
如果您的xargs
版本支持该-d
选项,则上面的命令将变得更简单:
$ grep -rl "needle text" my_folder | xargs -d '\n' -r file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable' | sed 's|:[^:]*$||'
我对组织的回答有两个问题:
它仅列出文本文件。它实际上并没有按要求搜索它们。要实际搜索,请使用
find . -type f -exec grep -Iq . {} \; -and -print0 | xargs -0 grep "needle text"
它为每个文件生成一个grep进程,这非常慢。那么一个更好的解决方案是
find . -type f -print0 | xargs -0 grep -IZl . | xargs -0 grep "needle text"
或简单地
find . -type f -print0 | xargs -0 grep -I "needle text"
与上述解决方案(2.5GB数据/ 7700文件)的4s相比,这仅需要0.2s,即20倍的速度。
同样,没有人引用ag,Silver Searcher或ack- grep¸作为替代方案。如果可以使用以下方法之一,则它们是更好的选择:
ag -t "needle text" # Much faster than ack
ack -t "needle text" # or ack-grep
最后,请注意误报(二进制文件作为文本文件)。我已经使用grep / ag / ack进行了误报,因此最好在编辑文件之前先列出匹配的文件。
这是简化版,其中提供了扩展的解释,适用于像我这样的初学者,他们正在尝试学习如何在一行中放置多个命令。
如果您要逐步写出问题,它将看起来像这样:
// For every file in this directory
// Check the filetype
// If it's an ASCII file, then print out the filename
要做到这一点,我们可以使用三种UNIX命令:find
,file
,和grep
。
find
将检查目录中的每个文件。
file
将给我们文件类型。就我们而言,我们正在寻找返回“ ASCII文本”
grep
将从以下输出中查找关键字“ ASCII” file
那么,如何将它们串联在一起?有多种方法可以执行此操作,但是我发现按照伪代码的顺序进行操作最有意义(尤其是对于像我这样的初学者)。
find ./ -exec file {} ";" | grep 'ASCII'
看起来很复杂,但是当我们分解它时还不错:
find ./
=浏览该目录中的每个文件。该find
命令会打印出与“表达式”匹配的任何文件的文件名,或路径之后的任何文件名(在我们的情况下为当前目录或./
要了解的最重要的事情是,第一位之后的所有内容都将被评估为True或False。如果为True,则将打印出文件名。如果不是,则命令继续。
-exec
=该标志是find命令中的一个选项,它使我们可以将某些其他命令的结果用作搜索表达式。就像在函数内调用函数一样。
file {}
=在中调用的命令find
。该file
命令返回一个字符串,告诉您文件的文件类型。通常,它看起来像这样:file mytextfile.txt
。在我们的例子中,我们希望它使用find
命令正在查看的任何文件,因此我们将花括号放在其中{}
以充当空变量或参数。换句话说,我们只是要求系统为目录中的每个文件输出一个字符串。
";"
=这是命令find
末尾的标点符号,也是标点符号-exec
。如果需要运行,请参见手册中的“查找”以获取更多说明man find
。
| grep 'ASCII'
= |
是管道。管道将左侧的所有内容作为输出,然后将其用作右侧的所有内容的输入。它获取find
命令的输出(字符串是单个文件的文件类型),并对其进行测试以查看其是否包含string 'ASCII'
。如果是,则返回true。
现在,find ./
当grep
命令返回true 时,右边的表达式将返回true。瞧
如果您有兴趣使用令人敬畏的file
实用程序并结合使用的功能,通过魔术字节查找任何文件类型find
,这会派上用场:
$ # Let's make some test files
$ mkdir ASCII-finder
$ cd ASCII-finder
$ dd if=/dev/urandom of=binary.file bs=1M count=1
1+0 records in
1+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.009023 s, 116 MB/s
$ file binary.file
binary.file: data
$ echo 123 > text.txt
$ # Let the magic begin
$ find -type f -print0 | \
xargs -0 -I @@ bash -c 'file "$@" | grep ASCII &>/dev/null && echo "file is ASCII: $@"' -- @@
输出:
file is ASCII: ./text.txt
图例:$
是交互式shell提示符,我们在其中输入命令
您可以在之后修改该部分&&
以调用其他脚本或也进行内联一些其他操作,即,如果该文件包含给定的字符串,请整理整个文件或在其中寻找辅助字符串。
说明:
find
文件项xargs
每个项目作为一行输入到一个衬里bash
命令/脚本中file
通过魔术字节grep
检查文件的类型,检查是否存在ASCII(如果存在),然后在&&
执行下一条命令后检查。find
将结果null
分开打印,这可以避免转义带有空格和元字符的文件名。xargs
,使用-0
option,将其null
分开读取,-I @@
获取每条记录并用作bash脚本的位置参数/ args。--
for bash
确保无论它后面是参数如何,即使它以-
like 开头,-c
否则也可以解释为bash选项如果您需要查找ASCII以外的grep ASCII
其他类型,只需将其替换为其他类型,例如grep "PDF document, version 1.4"
这个怎么样
find . -type f|xargs grep "needle text"
"needle text"
"needl text"
"needle text"
将找到包含二进制文件
find . -type f -exec grep -Il "" {} \;
。