ฉันจะ grep ในไฟล์ PDF ได้อย่างไร


135

มีวิธีการค้นหาไฟล์ pdf โดยใช้พลังของ grep โดยไม่ต้องแปลงเป็นข้อความเป็นอันดับแรกใน Ubuntu หรือไม่?


1
ฉันคิดว่าคุณต้องการที่จะแยกมัน PDF2Text เจ้าเพื่อให้ได้รับผลการใช้งานบางส่วนกลับ ...
โจฮาน


1
สำหรับผู้ที่มาที่นี่ด้วยการค้นหา: หากคุณยินดีที่จะแปลงเป็นไฟล์ข้อความเป็นอันดับแรกให้ดูที่วิธีค้นหาเนื้อหาของไฟล์ PDF หลายไฟล์?
Martin Thoma

คำตอบ:


135

ติดตั้งแพ็กเกจpdfgrepจากนั้นใช้คำสั่ง:

find /path -iname '*.pdf' -exec pdfgrep pattern {} +

------

วิธีที่ง่ายที่สุดคือ

pdfgrep 'pattern' *.pdf
pdfgrep 'pattern' file.pdf 

5
ใช้งานได้ใน mac osx (Mavericks) เช่นกัน ติดตั้งโดยใช้การชง ง่าย ขอบคุณ
mikiemorales

7
ฉันได้ตรวจสอบแหล่งที่มาของ pdfgrep และใช้ poppler เพื่อแยกสตริงออกจาก pdf เกือบจะเหมือนกับคำตอบของ @ wag เพียง pagewise แทนที่จะสันนิษฐานว่าเป็นเอกสารทั้งหมด
Andrew Martin

4
pdfgrepยังมีธงแบบเรียกซ้ำ pdfgrep -R pattern /path/ดังนั้นคำตอบนี้อาจอาจจะลดลงไป: แม้ว่ามันจะมีประสิทธิภาพน้อยลงหากไฟล์นั้นผ่านทุกไฟล์แม้ว่าจะไม่ใช่ไฟล์ PDF ก็ตาม และฉันสังเกตว่ามันมีปัญหากับตัวละครนานาชาติเช่นå, äและö
Rovanion

1
ที่จริงแล้ว-nตัวเลือกนี้เป็นมืออาชีพสำหรับ pdfgrep เนื่องจากช่วยให้รวมหมายเลขหน้าในผลลัพธ์ (อาจเป็นประโยชน์สำหรับการประมวลผลเพิ่มเติม)
JepZ

4
คำตอบนี้จะใช้ง่ายขึ้นหากอธิบายว่าบิตของคำสั่งนั้นหมายถึงการคัดลอกตัวอักษรและตัวยึดตำแหน่งใด อะไรนะpattern? อะไรนะ{}? มีอะไรขึ้นกับ `+ ' ฉันไม่รู้ว่าเมื่ออ่านครั้งแรก ... ดังนั้นไป manpage ฉันไปฉันคิดว่า
Mark Amery

56

หากคุณpoppler-utilsติดตั้ง (เริ่มต้นบน Ubuntu Desktop) คุณสามารถ "แปลง" ได้ทันทีและไปที่grep:

pdftotext my.pdf - | grep 'pattern'

สิ่งนี้จะไม่สร้างไฟล์. txt


1
ดังนั้น .. คุณแยกข้อความก่อนที่จะ grep ซึ่งหมายความว่าคำตอบคือ "ไม่"
akira

18
@akira OP อาจหมายถึง "โดยไม่ต้องเปิด PDF ในมุมมองและส่งออกไปยังข้อความ"
Michael Mrozek

5
@akira คุณเห็นคำว่า "grep only" ที่ไหน?
Michael Mrozek

6
@ akira ฉันพูดไปแล้วว่าฉันคิดว่าเขาน่าจะหมายถึงอะไร เขาไม่ต้องการที่จะส่งออกไปยังข้อความก่อนที่จะประมวลผล ฉันสงสัยมากว่าเขามีปัญหากับคำสั่งใด ๆที่แปลงเป็นข้อความในทางใดทางหนึ่ง ไม่มีเหตุผลที่จะไม่
Michael Mrozek

2
@sellellbc อาร์กิวเมนต์ที่สองpdftotextคือชื่อไฟล์ที่ควรเขียน อย่างไรก็ตามโดยทั่วไปแล้วเครื่องมือมักจะอนุญาตให้คุณเขียนstdoutแทนไฟล์ได้โดยระบุ-แทน ในทำนองเดียวกันเครื่องมือบางอย่างจะเขียนถึงstdoutค่าเริ่มต้นหากคุณไม่ใช้อาร์กิวเมนต์ดังกล่าวทั้งหมด (แต่ไม่สามารถทำได้ตลอดเวลาหากไม่ได้สร้างความคลุมเครือ)
Joost

11

pdfgrepเขียนขึ้นเพื่อจุดประสงค์นี้โดยแท้และมีอยู่ใน Ubuntu

มันพยายามที่จะเข้ากันได้เป็นส่วนใหญ่grepและทำให้ "พลังแห่ง grep" โดยเฉพาะสำหรับ PDF ซึ่งรวมถึงตัวเลือก grep ทั่วไปเช่น--recursive, หรือ--ignore-case--color

ในทางตรงกันข้ามpdftotext | greppdfgrep สามารถส่งออกหมายเลขหน้าของการแข่งขันในลักษณะนักแสดงและโดยทั่วไปจะเร็วกว่าเมื่อไม่ต้องค้นหาเอกสารทั้งหมด (เช่น--max-countหรือ--quiet)

การใช้งานพื้นฐานคือ:

pdfgrep PATTERN FILE..

PATTERNสตริงการค้นหาของคุณอยู่ที่ไหนและFILEรายชื่อไฟล์ (หรือไวด์การ์ดในเชลล์)

ดูmanpageสำหรับข่าวสารเพิ่มเติม


7

เลขที่

ไฟล์ PDF ประกอบด้วยข้อมูลจำนวนหนึ่งบางส่วนเป็นข้อความรูปภาพบางรูปและบางส่วนเป็นไฟล์ XYZ แฟนซีที่น่าอัศจรรย์อย่างแท้จริง (เช่นไฟล์. u3d) ชิ้นส่วนเหล่านั้นส่วนใหญ่ถูกบีบอัด (เช่นแบนตรวจสอบhttp://www.verypdf.com/pdfinfoeditor/compression.htm ) เพื่อที่จะ 'grep' a .pdf คุณต้องย้อนกลับการบีบอัด aka แยกข้อความ

คุณสามารถทำได้ทั้งไฟล์ด้วยเครื่องมือเช่นpdf2textและ grep ผลลัพธ์หรือคุณเรียกใช้ 'indexer' (ดูที่xapian.orgหรือlucene ) ซึ่งสร้างดัชนีที่ค้นหาได้จากไฟล์. pdf ของคุณจากนั้นคุณสามารถใช้การค้นหา เครื่องมือเอ็นจิ้นของตัวสร้างดัชนีนั้นเพื่อรับเนื้อหาของ pdf

แต่ไม่คุณไม่สามารถgrepไฟล์ PDF และหวังว่าจะได้คำตอบที่เชื่อถือได้โดยไม่ต้องแยกข้อความออกก่อน


5
เมื่อพิจารณาpdfgrepอยู่ (ดูด้านบน) แบน "ไม่" ไม่ถูกต้อง
Jonathan Cross

6

Recollสามารถค้นหา PDF มันไม่รองรับการแสดงออกปกติ แต่มีตัวเลือกการค้นหาอื่น ๆ อีกมากมายดังนั้นมันอาจเหมาะสมกับความต้องการของคุณ


5

คุณสามารถผ่านมันได้stringsก่อน: -

cat file.pdf | strings | grep <...etc...>

8
เพียงใช้strings file.pdf | grep <...>คุณไม่จำเป็นต้องใช้cat
phunehehe

ใช่ - ใจของฉันทำงานได้ดีกับลำธาร ... :-)
Andy Smith

12
จะไม่ทำงานหากข้อความถูกบีบอัดซึ่งเป็นส่วนใหญ่
akira

6
แม้ว่าข้อความนั้นจะไม่ถูกบีบอัด แต่โดยทั่วไปแล้วจะเป็นประโยคเล็ก ๆ (ไม่จำเป็นต้องมีทั้งคำ! ไม่เป็นมิตรมากหรือstrings grep
Jander

คุณลองคิดอีกเหตุผลว่าทำไมการใช้สตริงสำหรับสิ่งนี้ไม่ทำงาน ฉันพบว่าการใช้สตริงทำงานบนไฟล์ PDF บางตัว แต่ไม่ใช่ไฟล์อื่น ๆ
Hourback

3

ลองดูที่เครื่องมือ grep ทรัพยากรทั่วไปcrgrepซึ่งรองรับการค้นหาภายในไฟล์ PDF

นอกจากนี้ยังช่วยให้ค้นหาทรัพยากรอื่น ๆ เช่นเนื้อหาที่ซ้อนในคลังข้อมูลตารางฐานข้อมูลเมตาดาต้าการพึ่งพาไฟล์ POM และแหล่งข้อมูลบนเว็บ - และการรวมกันของสิ่งเหล่านี้รวมถึงการค้นหาแบบเรียกซ้ำ


2

ลองนี้

find /path -iname *.pdf -print0 | for i in `xargs 0`; do echo $i; \
    pdftotext "$i" - | grep pattern; done

สำหรับการพิมพ์บรรทัดลวดลายที่เกิดขึ้นภายใน pdf


2

cd ไปยังโฟลเดอร์ที่มีไฟล์ pdf ของคุณแล้ว ..

pdfgrep 'pattern' your.pdf

หรือหากคุณต้องการค้นหาไฟล์ PDF มากกว่าหนึ่งไฟล์ (เช่นในไฟล์ pdf ทั้งหมดในโฟลเดอร์ของคุณ)

pdfgrep 'pattern'  `ls *.pdf`

หรือ

pdfgrep 'pattern' $(ls *.pdf)

เหตุใดคุณจึงใช้ ls เพื่อใส่ชื่อไฟล์ในพารามิเตอร์ มันไม่เพียง แต่ช้าลง แต่ยังเป็นความคิดที่ดีที่จะใช้lsการส่งออกเป็น input ในการคำสั่งอื่น เพียงแค่pdfgrep 'pattern' *.pdfเป็นพอ
phuclv

1

มีคำถามซ้ำกันใน StackOverflow คนที่นั่นแนะนำการเปลี่ยนแปลงของ harish.venkarts ตอบ:

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

ข้อได้เปรียบเหนือคำตอบที่คล้ายกันที่นี่คือ--with-filenameธงสำหรับ grep สิ่งนี้ค่อนข้างดีกว่า pdfgrep เช่นกันเนื่องจาก grep มาตรฐานมีคุณสมบัติมากกว่า

https://stackoverflow.com/questions/4643438/how-to-search-contents-of-multiple-pdf-files


ฉันคิดว่ามันจะเป็นการดีกว่าถ้าคุณปล่อยให้สิ่งนี้เป็นความคิดเห็น (หรือแก้ไข) ในคำตอบที่คล้ายกันที่คุณอ้างถึง
Bernhard

0

นี่คือสคริปต์ด่วนสำหรับค้นหา pdf ในไดเรกทอรีปัจจุบัน:

#!/bin/bash

if [ $# -ne 1 ]; then
  echo "usage $0 VALUE" 1>&2
  exit 1
fi

echo 'SEARCH IS CASE SENSITIVE' 1>&2

find . -name '*.pdf' -exec /bin/bash -c 'pdftotext "{}" - | grep --with-filename --label="{}" --color "$0"' $1 \;

0

ผมถือว่าคุณหมายถึง TP ไม่แปลงบนดิสก์คุณสามารถแปลงให้stdoutแล้ว grep pdftotextมันด้วย การแปลงไฟล์ PDF เป็นไฟล์ ๆ โดยไม่มีการแปลงใด ๆ นั้นไม่ใช่วิธีการปฏิบัติเพราะPDFส่วนใหญ่เป็นรูปแบบไบนารี

ในไดเรกทอรี:

ls -1 ./*.pdf | xargs -L1 -I {} pdftotext {}  - | grep "keyword"

หรือในไดเรกทอรีและไดเรกทอรีย่อย:

tree -fai . | grep -P ".pdf$" | xargs -L1 -I {} pdftotext {}  - | grep "keyword"

นอกจากนี้เนื่องจากบางpdfสแกนจะต้องมี OCR ก่อน ฉันเขียนวิธีง่ายๆในการค้นหาไฟล์ PDF ทั้งหมดที่ไม่สามารถgreped และ OCR ได้

ฉันสังเกตว่าpdfไฟล์ไม่มีตัวอักษรใด ๆ มันมักจะไม่สามารถค้นหาได้ pdffontsดังนั้นการรู้นี้เราสามารถใช้

2 บรรทัดแรกของpdffontsส่วนหัวเป็นส่วนหัวของตารางดังนั้นเมื่อไฟล์ที่ค้นหาได้มีเอาต์พุตมากกว่าสองบรรทัดรู้ว่าเราสามารถสร้าง:

gedit check_pdf_searchable.sh

จากนั้นวางสิ่งนี้

#!/bin/bash 
#set -vx
if ((`pdffonts "$1" | wc -l` < 3 )); then
echo $1
pypdfocr "$1"
fi

จากนั้นทำให้สามารถเรียกใช้งานได้

chmod +x check_pdf_searchable.sh

จากนั้นแสดงรายการไฟล์ PDF ที่ไม่สามารถค้นหาได้ทั้งหมดในไดเรกทอรี:

ls -1 ./*.pdf | xargs -L1 -I {} ./check_pdf_searchable.sh {}

หรือในไดเรกทอรีและไดเรกทอรีย่อย:

tree -fai . | grep -P ".pdf$" | xargs -L1 -I {} ./check_pdf_searchable.sh {}

0

หากคุณต้องการค้นหาชื่อ / คุณสมบัติของไฟล์ PDF ... หรือสตริงแบบง่าย ๆ ที่ไม่ถูกบีบอัดหรือเข้ารหัสแล้วแทนที่จะใช้stringsคุณสามารถใช้ด้านล่าง

grep -a STRING file.pdf
cat -v file.pdf | grep STRING

จากgrep --help:

      --binary-files=TYPE   assume that binary files are TYPE;
                            TYPE is 'binary', 'text', or 'without-match'
  -a, --text                equivalent to --binary-files=text

และcat --help:

  -v, --show-nonprinting   use ^ and M- notation, except for LFD and TAB

0

gpdf อาจเป็นสิ่งที่คุณต้องการหากคุณใช้ Gnome! ตรวจสอบนี้ในกรณีที่คุณไม่ได้ใช้คำพังเพย มีรายการของผู้ชมไฟล์ PDF ของ CLI จากนั้นคุณสามารถใช้grepเพื่อค้นหารูปแบบบางอย่าง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.