如何搜索多个pdf文件的内容?

如何在目录/子目录中搜索PDF文件的内容?我在找一些命令行工具。grep似乎不能搜索PDF文件。

130040 次浏览

你需要一些工具,如pdf2text,首先将pdf转换为文本文件,然后在文本中搜索。(您可能会错过一些信息或符号)。

如果你正在使用一种编程语言,很可能有专门为此目的编写的pdf库。例如:Perl的http://search.cpan.org/dist/CAM-PDF/

你的发行版应该提供一个名为pdftotext的实用程序:

find /path -name '*.pdf' -exec sh -c 'pdftotext "{}" - | grep --with-filename --label="{}" --color "your pattern"' \;

"-"是将pdftotext输出到标准输出而不是文件的必要条件。 --with-filename--label=选项将把文件名放在grep的输出中。 可选的--color标志很好,它告诉grep在终端上使用颜色输出

(在Ubuntu中,pdftotext由包xpdf-utilspoppler-utils提供。)

如果你想使用GNU greppdfgrep不支持的特性,这个使用pdftotextgrep的方法比pdfgrep更有优势。请注意: pdfgrep - 1.3。x支持-C选项打印上下文行。

试着在一个简单的脚本中使用'acroread',就像上面那样

pdfgrep,它做的正是它的名字所暗示的。

pdfgrep -R 'a pattern to search recursively from path' /some/path

我用它做过简单的搜索,效果很好。

(Debian、Ubuntu和Fedora中都有软件包。)

自1.3.0版本起,pdfgrep支持递归搜索。这个版本从Ubuntu 12.10 (Quantal)开始在Ubuntu中可用。

这个具有破坏性的小脚本。祝你玩得开心。

function pdfsearch()
{
find . -iname '*.pdf' | while read filename
do
#echo -e "\033[34;1m// === PDF Document:\033[33;1m $filename\033[0m"
pdftotext -q -enc ASCII7 "$filename" "$filename."; grep -s -H --color=always -i $1 "$filename."
# remove it!  rm -f "$filename."
done
}

我也遇到了同样的问题,因此我写了一个脚本,搜索指定文件夹中的所有pdf文件的字符串,并打印匹配查询字符串的pdf文件。

也许这对你有帮助。

你可以下载它在这里

如果你想使用pdftotext查看文件名,使用以下命令:

find . -name '*.pdf' -exec echo {} \; -exec pdftotext {} - \; | grep "pattern\|pdf"

Recoll是一个很棒的Unix/Linux全文GUI搜索应用程序,支持几十种不同的格式,包括PDF。它甚至可以将查询的确切页码和搜索词传递给文档查看器,从而允许您直接从它的GUI跳转到结果。

Recoll还提供了一个可行的命令行界面和浏览器界面

有一个开源的公共资源grep工具crgrep,它可以在PDF文件中搜索,但也可以搜索其他资源,如档案中嵌套的内容、数据库表、图像元数据、POM文件依赖项和web资源——以及这些资源的组合,包括递归搜索。

Files选项卡下的完整描述几乎涵盖了该工具支持的内容。

我开发的crgrep是一个开源工具。

我的实际版本的pdfgrep(1.3.0)允许以下:

pdfgrep -HiR 'pattern' /path

当执行pdfgrep --help时:

  • H:打印每个匹配项的文件名。
  • i:忽略大小写区别。
  • R:递归搜索目录。

它在我的Ubuntu上运行得很好。

我喜欢@sjr的答案,但我更喜欢xargs vs -exec。我发现xargs更通用。例如,使用-P,我们可以在必要时利用多个cpu。

find . -name '*.pdf' | xargs -P 5 -I % pdftotext % - | grep --with-filename --label="{}" --color "pattern"

首先将所有pdf文件转换为文本文件:

for file in *.pdf;do pdftotext "$file"; done

然后像往常一样使用grep。这是特别好的,因为当您有多个查询和许多PDF文件时,它是快速的。

还有一个名为ripgrep-all的实用程序,它基于ripgrep

它不仅可以处理PDF文档,比如Office文档和电影,而且作者索赔它比pdfgrep更快。

递归搜索当前目录的命令语法,第二个命令只限制PDF文件:

rga 'pattern' .
rga --type pdf 'pattern' .

谢谢所有的好主意!

我尝试了xargs方法,但正如这里所指出的,xargs将使它不可能(或非常困难)包括打印实际的文件名……

所以我用GNU平行尝试了整个事情。

parallel "pdftotext -q {} - | grep --with-filename --label='['{}']' --color=always --context=5 'pattern'" ::: *.pdf
  • 这不仅打印了模式,而且还打印了--context=5的上下5行作为上下文。
  • 使用-q pdftotext将不会打印任何错误消息或警告(quiet)。
  • 我使用括号[]代替括号{}作为标签。如果你想要大括号--label='{'{}'}'会实现。注意,{}被实际的文件名替换为GNU并行文件,例如'Example portable document file name with spaces.pdf' ({}已经使用单引号')。
  • 使用--label={}只会打印文件名,这可能是显示文件名的最佳方式。
  • 我还注意到,当我尝试输出时,输出是没有颜色的,除非用grep添加--color=always来强制输出。
  • --ignore-case添加到grep命令中用于不区分大小写的关键字搜索可能很有用。

如果所有PDF文件都应该递归处理,包括当前目录(.)中的所有子目录,这可以通过find来完成:

find . -type f -iname '*.pdf' -print0 | parallel -0 "pdftotext -q {} - | grep --with-filename --label='['{}']' --color=always --context=5 'pattern'"
  • 使用find, -iname '*.pdf'不区分大小写。-name '*.pdf'只包含小写的.pdf文件(正常情况下)。由于我有时也会遇到Windows pdf文件带有大写的.PDF文件扩展名,我倾向于使用-iname
  • 上面的命令还可以使用-print查找选项(而不是-print0),因此它将是基于行的(每行一个文件名),那么并行命令中必须省略-0 (NUL分隔符)。
  • 同样,在grep命令中包含--ignore-case将使搜索不区分大小写。

作为处理整个命令行的一般建议,parallel --dry-run将打印将要执行的命令。

$ find . -type f -iname '*.pdf' -print0 | parallel --dry-run -0 "pdftotext -q {} - | grep --with-filename --label='['{}']' --color=always --ignore-case --context=5 'pattern'"
pdftotext -q ./test PDF file 1.pdf - | grep --with-filename --label='['./test PDF file 1.pdf']' --color=always --ignore-case --context=5 'pattern'
pdftotext -q ./subdir1/test PDF file 2.pdf - | grep --with-filename --label='['./subdir1/test PDF file 2.pdf']' --color=always --ignore-case --context=5 'pattern'
pdftotext -q ./subdir2/test PDF file 3.pdf - | grep --with-filename --label='['./subdir2/test PDF file 3.pdf']' --color=always --ignore-case --context=5 'pattern'

使用pdfgrep:

pdfgrep -HinR 'FWCOSP' DatenModel/

在这个命令中,我在文件夹DatenModel/中搜索单词FWCOSP

正如你在输出中看到的,你可以有文件名和行号:

enter image description here

我使用的选项是:

-i : Ignores, case for matching
-H : print the file name for each match
-n : prefix each match with the number of the page where it is found
-R : same as -r, but it also follows all symlinks.