我正在尝试查找保存在外部备份驱动器上的客户 pdf 文件,其中包含 8000 多个 pdf 文件和数百个文件夹。
例如,如果我想搜索驱动器 X: 上包含我的客户名称“Sequoia Group”的所有 pdf 文件,有哪些有用的命令行和/或工具来实现相关的输出结果?
我使用的是 MacOS High Sierra,带有 zsh,我还通过自制程序安装了 GNU grep、ack 和 pdfgrep。但是,我还没有找到该文件。
文件名未知,因为所有文件都保存为 PDF-Backup-0001、PDF-Backup-0002...等,
到目前为止,我使用了以下命令,但没有成功:
#grep -wirl "sequoia group" ./
#pdfgrep -iHncRZ "sequoia group"
#mdfind "sequoia group"
另外,建议使用此命令行,但是,我不确定在哪里放置名称,因此我将 /path 替换为驱动器的路径,并将模式替换为“sequoia”,仍然没有找到任何匹配项
#find /path -iname '*.pdf' -exec pdfgrep pattern {} +
#find /Volumes/X Backup -iname '*.pdf' -exec pdfgrep "sequoia" {} +
答案1
啊,这怎么这么熟悉啊……
在搜索目录的根目录中打开一个终端,然后
pdfgrep -ril "sequoia group" >matches 2>bad.files
这将递归地-r
搜索所有 pdf 文件中的搜索词,不区分大小写-i
,并且仅返回文件名,而不返回匹配的文本-l
。
所有匹配的文件名都将写入名为 的文件matches
,任何错误都将写入名为 的文件bad.files
。
您matches
可以将其复制到单独的目录以供参考。
while read f do; cp $f /wherever/I/want/$f; done < matches
它们bad.files
要么已损坏,要么 OCR 不正确,因此您应该将它们复制到另一个目录,重新处理它们并再次搜索它们。
如果您急于使用,find
因为您可能有等的变体pdf
,PDF
那么
find /search/root/ -iname *.pdf -exec pdfgrep -il "sequoia group" {} ';' >matches 2>bad.files
您在上面要求对此进行解释...find
我认为您得到的命令pdfgrep
在上面进行了解释,重定向也是如此>
。
选项-exec
获取命令find
的输出find
并将其放在您看到的位置{}
。
最后-exec
你会看到我已经放了,;
而你已经放了+
。
+
导致-exec
收集所有输出find
并将其pdfgrep
作为一长串参数传递给并运行 pdfgrep 一次。除非文件数量超过最大数量,否则工作正常。
;
导致一次将-exec
的输出提供find
给一个文件。pdfgrep
后记。打开一些 pdf 文件,无论您用什么方式查看它们,并确保它们已经过 OCR 并且实际上是可搜索的。
如果不是,您可能需要从每个目录运行它
find /path/to/dir/ -maxdepth 1 -type f -iname "*.pdf" -print0 | while IFS= read -r -d $'\0' line; do pdfsandwich -lang eng "$line"; done
如果您可以让您的电脑专门处理所有 8,000 个文件,无论需要多长时间,那么只需删除-maxdepth 1
并指向find
您的搜索根目录即可。
答案2
首先,正如 @Motivated 在评论中询问的那样:PDF 是通过扫描纸质文档生成的还是通过某些程序(LibreOffice、Tex/LaTeX、MS Word 等)生成的?如果它们是扫描文档,那么这些方法将不是工作:您需要一个 OCR 程序将图像翻译成文本,然后您可以进行搜索。这可能是一个超出本答案范围的重大项目。在下文中,我假设这些 PDF 是由某些文字处理(或类似)程序生成的。特别是,pdfgrep
假设可以有效地处理这些文件。
你需要两件事:
一个程序,它将遍历目录层次结构,查找该层次结构中的所有匹配文件,并对找到的每个文件执行某些操作。就是这样
find
。例如,您可以说find /path/to/some/directory -type f -name 'PDF-Backup-*'
并且find
会找到所有常规文件(-type f
),其名称以PDF-Backup-
任何地方在给定路径下/path/to/some/directory
- 默认操作是打印找到的每个文件的路径名。一旦找到您感兴趣的所有文件,您需要一个程序来搜索每个文件中的给定字符串:
pdfgrep
将在这里工作(假设我们不属于上面讨论的扫描文件类别),但您想要给出它有一些选项:-i
不区分大小写地搜索文件中的模式,因此pdfgrep -i sequia
会找到sequoia
,Sequioa
,SEQUOIA
等SeQuOiA
,而不考虑大小写 - 这可能就是您想要的,除非您是真的确定它在文件中的拼写方式,并且与大小写无关的搜索会产生太多误报。您需要的另一个选项是-H
:打印出找到匹配项的文件名[fn:1]。
现在您可以将两者结合起来:调用find
来遍历层次结构,查找与条件匹配的所有文件,但不要让它对它使用默认操作(打印文件名)找到的每个文件进行操作,而是要求它执行不同的操作:在每个文件中搜索带有pdfgrep
.您可以使用以下-exec
选项来做到这一点find
:
find /path/to/some/directory -type f -name 'PDF-Backup-*' -exec pdfgrep -i -H sequoia '{}' \;
语法有点晦涩:{}
被调用中找到的每个文件替换pdfgrep
,但由于大括号通常在 shell 中具有特殊含义,因此必须用引号引起来的大括号对。此外,;
终止作为 参数的命令-exec
,但它对 shell 也有特殊含义,并且必须用引号引起来 - 在本例中用单个反斜杠而不是两个引号,只是因为它更短。请确保完全按照所示内容输入这些内容。
[fn:1] 当搜索两个或多个文件时,文件名默认打印出来pdfgrep
,但是当与上面最后一个项目符号结合pdfgrep
使用时,会分别调用每个文件,因此默认情况下不打印文件名:这就是为什么是需要的。find
pdfgrep
-H