0

I am trying to locate a client's pdf file that was saved on an external backup drive, which contains a little over 8000 pdf files and hundreds of folders.

For example, if I want to search all pdf files on drive X: that contains my client's name "Sequoia Group", what are some useful command lines and/or tools to achieve relevant output results?

I'm using MacOS High Sierra, with zsh, I've also installed GNU grep, ack, and pdfgrep via homebrew. However, I haven't been able to find the file yet.

Filename is unkown, since all files were saved as PDF-Backup-0001, PDF-Backup-0002...etc.,

I used the following commands so far with no luck:

#grep -wirl "sequoia group" ./

#pdfgrep -iHncRZ "sequoia group"

#mdfind "sequoia group"

Also, this command line was suggested, however, I am not sure where to put the name, so I replaced /path with the drive's path, and pattern with "sequoia", still did not find any matches

#find /path -iname '*.pdf' -exec pdfgrep pattern {} + 
#find /Volumes/X Backup -iname '*.pdf' -exec pdfgrep "sequoia" {} + 
  • I don't have a Mac to test this, but can you try pdfgrep -r --include "*.pdf" pattern and see if it works? You'd run that from the top directory, which is '/Volumes/X Backup' in your case. – Haxiel Jan 26 at 16:15
  • @DiFrag - Judging by the file names, are these scanned documents? – Motivated Jan 26 at 16:22
  • I just tried it, didn't work. Here is the output:pdfgrep: Could not search in page 72 of .pdfgrep: Could not search in page 72 of ./Backups/Clients/XXXX00/XXXX.pdf Could not search in page 47 of ./Backups/Clients/XXXX01/XXXX.pdf – DiFrag Jan 26 at 16:23
  • @DiFrag - Have you looked at the options at (unix.stackexchange.com/questions/6704/…)? – Motivated Jan 26 at 16:24
  • I did, this is where I found the "find /path -iname '*.pdf' -exec pdfgrep pattern {} + ", which I still don't fully understand that command, I tried it as stated above in my question, but it didn't work. Please feel free to explain that command further if you don't mind – DiFrag Jan 26 at 16:28
1

First, as @Motivated asks in a comment: are the PDFs produced from scanning paper documents or are they produced from some program (LibreOffice, Tex/LaTeX, MS Word, etc)? If they are scanned documents, then these methods will NOT work: you will need an OCR program to translate the images into text which you can then search. That is probably a major project that is beyond the scope of this answer. In the following, I assume that these PDFs have been produced from some word-processing (or similar) program. In particular, pdfgrep is assumed to work effectively on these files.

You need two things:

  • a program that will walk a directory hierarchy, find all the matching files in that hierarchy and perform some action on each file it finds. That's what find does. E.g you can say find /path/to/some/directory -type f -name 'PDF-Backup-*' and find will find all regular files (-type f), whose name starts with PDF-Backup- anywhere under the given path /path/to/some/directory - the default action is to print the pathname of each file found.

  • Once you find all the files you are interested in, you need a program to search each one for the given string: pdfgrep will work here (assuming we don't fall into the category of scanned files as discussed above), but you want to give it some options: -i searches a file for a pattern case-insensitively, so pdfgrep -i sequia will find sequoia, Sequioa, SEQUOIA, SeQuOiA etc. without regard to case - this is probably what you want, unless you are really sure of how it is spelt in the file and the case-independent search produces too many false positives. The other option that you will want is -H: that prints out the filename where the match was found [fn:1].

Now you can combine the two: invoke find to walk the hierarchy, finding all the files that match the criteria, but instead of having it act on each file it finds with the default action (print the filename), ask it to perform a different action: search each file for a pattern with pdfgrep. You do that by using the -exec option of find:

find /path/to/some/directory -type f -name 'PDF-Backup-*' -exec pdfgrep -i -H sequoia '{}' \; 

The syntax is a bit arcane: {} is replaced by each file found in the invocation of pdfgrep but since braces usually have special meaning in the shell, the pair of braces has to be quoted. In addition the ; terminates the command that is the argument of -exec, but it too has special meaning to the shell and has to be quoted - in this case by a single backslash, rather than two quotes, only because it's shorter. Just be sure to type these things exactly as shown.

[fn:1] The filename is printed out by default when pdfgrep searches two or more files, but when using pdfgrep in conjunction with find as in the last bullet above, pdfgrep is invoked with each file separately, so the filename is not printed by default: that's why -H is needed.

  • All pdf files are OCR, even the ones that were scanned had been converted to OCR. Most if not all of those pdfs have been converted from word .doc documents. – DiFrag Jan 26 at 20:15
  • @DiFrag: OCR (optical character recognition) is a technique for extracting text from image files (JPG, TIFF, PNG, whatever) - it is not a file type. So I'm not sure what you are saying here. – NickD Jan 26 at 22:10
1

Oh, how familiar this is.....

Open a terminal at the root of your search directory and

pdfgrep -ril  "sequoia group" >matches 2>bad.files

This will recursively, -r, search all pdf files for the search term, case insensitive -i, and return only the file names and not the matched text -l.

All of the matching file names will be written to the file called matches and any errors will go to a file called bad.files.

The matches you can copy to a separate directory for reference.

while read f do; cp $f /wherever/I/want/$f; done < matches

The bad.files are either corrupt or not OCR properly so you should copy them to another directory, reprocess them and search them again.

If you are desperate to use find because you may have variants of pdf, PDF etc then

find /search/root/ -iname *.pdf -exec pdfgrep -il "sequoia group" {} ';' >matches 2>bad.files

You asked for an explanation of this above.... the find command I think you get, the pdfgrep is explained above as are the redirects >.

The -exec option of find takes the output of the find command and puts it where you see the {}.

At the end of the -exec you will see I have put ; while you have +.

+ causes -exec to collect all of the output from find and passes it to pdfgrep as a long list of arguments and runs pdfgrep once. Works fine unless the number of files exceeds the maximum.

; causes -exec to feed the output of find to pdfgrep one file at a time.

Postnote. Open a few pdfs in whatever you use to view them and make sure they have been OCR and are in fact searchable.

If they are not you may need to run this from each directory

find /path/to/dir/ -maxdepth 1 -type f -iname "*.pdf" -print0 | while IFS= read -r -d $'\0' line; do pdfsandwich -lang eng "$line"; done

If you can dedicate your PC to processing all 8,000 files for however long it takes then just delete the -maxdepth 1 and point find at the root of your search.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.