1

I have a logfile with some filenames inbetween other events, which I need to find in subfolders. Same necessity for filenames inside xml files which has to be found inside some folder and subfolders. Looks to me I should use grep on the logfile and extract exact filenames, feed those to find. I can easily get a list of filenames one per line, but getting it to work with find is not exactly working. And internet is full with answers for other way around - find results feeding into grep.

grep -oP '(?<=Some problem with file named ).*pdf?(?=\.)' /home/myname/log/myspecificlogfile.log

I tried piping results of this command to xargs and find, but it doesnt give any results both on files not actually there and ones there. Echo is just to simplify, find parameter -ls is not yet added (but I will need it):

echo 12345.pdf | xargs -0 -I{} find /home/myname/workfolders/ -name '{}'    #Nonexisting pdf
echo 67890.pdf | xargs -0 -I{} find /home/myname/workfolders/ -name '{}'   #Existing pdf, no results

How do I get grep results piped to find to find my files in a folder and eventually subfolders?

  • Is that ? after pdf intended? That would be like (pdf|pd). – Stéphane Chazelas Nov 15 '16 at 13:59
  • The questionmark is part of the Perl grep to be able to find specific pattern, where middle is not known, but pump out only the middle. Like finding contents of an xml tag, which happens to be a filename. In this case it is a text with specific error/warning aaa followed by a filename bbb and ended with period ccc: (?<=aaa)bbb?(?=ccc) – uldics Nov 15 '16 at 20:40
  • b? is an optional b (0 or 1 b, same as b{0,1}). bbb? is two bs followed by an optional b. pdf is pd followed by an optional f. Which doesn't sound like that's what you'd want. – Stéphane Chazelas Nov 15 '16 at 21:11
  • Ohh, yes, optional preceding character! My bad. Thank you. Somehow it sneaked in there, but fortunately worked out, as I don't have any .pd files. – uldics Nov 15 '16 at 21:34
2

I'd do:

grep -oP '(?<=Some problem with file named ).*pdf(?=\.)' \
  /home/myname/log/myspecificlogfile.log | awk -F / '
     ARGIND == 1 {files[$0]; next}
     $NF in files' - RS='\0' <(
     find /home/myname/workfolders/ -name '*pdf' -type f -print0)

(assumes the GNU implementation of grep and awk and a shell with support for process substitution like ksh, zsh or bash).

Using find's -name would not be ideal for files names *.pdf or ?.pdf for instance. Running one find per file name would be inefficient. Even if you made a solution that calls one find with -name a.pdf -o -name b.pdf... that would probably still be less efficient than a hash lookup as done by awk.

  • But isn't this also performing a pretty wide search - returning all my files ('*pdf') and then doing awk on them? Or is it that the find gets somehow modified arguments from awk? Probably just me not yet quite understanging the sequence of actions. – uldics Nov 15 '16 at 21:12
  • @uldics, find finds the pdf files, awk post-processes it to select only the ones whose base name ($NF, the last field, in the / separated (-F /) list of fields or each NUL delimited (RS='\0') record) have been found in the log file. – Stéphane Chazelas Nov 15 '16 at 21:16
0

Other variant to use find + grep

find /home/myname/workfolders/ \
     -name '*pdf' -type f -exec grep -qFf \
          <(grep -oP '(?<=Some problem with file named ).*pdf?(?=\.)'\
                 /home/myname/log/myspecificlogfile.log) \
     -print

Or you can divide it in two command with pipe

find /home/myname/workfolders/ -name '*pdf' -type f |
grep -qFf <(grep -oP '(?<=Some problem with file named ).*pdf?(?=\.)' \
            /home/myname/log/myspecificlogfile.log)
  • Looks like this would not be applicable to my situation, as I have hundreds of thousands pdf files, but only problems on some 10-100 files logged. But yes, it could be good in other cases, not so specific as mine. – uldics Nov 15 '16 at 20:37

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.