0
find . -name "*.ooutline" -print0 | xargs -0 -n1 unzip -c | grep  -m 10 -Eo ".{0,20}$1.{0,20}" 

".ooutline' files are zipped OmniOutliner files. I want to find them, including recursively in subdirectories; pipe the names to unzip; have unzip unzip each .ooutline file into memory; then grep the contents of the unzipped file in memory.

I haven't had much luck trying to do this with find. I do have a working bash shell script, as follows:

#!/bin/bash

for file in *.ooutline; do
    if ( unzip -c "$file" |   grep --label="$file" -H  -m 10 -Eo ".{0,20}$1.{0,20}"  )  ; then
        printf "\n\n"
    fi
done

I'd like to be able to do this on one line with find. I'd appreciate any advice on this. Thank you.

THE NEXT DAY

Progress! This works but only on the one of the files in the list. This means the idea is right, but I have some detail wrong. Note: I got the find-exec-unzip idea from another post on stack: I do have filenames with spaces.

find . -name '*.zip' -exec sh -c 'unzip -c -d "`dirname \"{}\"`" "{}"' ';' | grep  -m 10 -Eo ".{0,20}Peter.{0,20}"

I tried this

find . -name '*.zip' -exec sh -c 'unzip -c  "{}"' ';' | grep  -m 10 -Eo ".{0,20}Peter.{0,20}"

and it returned these results

Version Peter sleep and wa reason they brought Peter here for this missi Dr Adkins finds Peter on his knees prayin g outside ICU. Peter is convinced Five i s not go there yet. Peter gives him a speech

...so it's definitely returning something from one file (an analysis of a science fiction novel).

johnrubythecat
  • 1,003
  • 1
  • 13
  • 31
  • I'm curious, why do you want to do it in one line? – cdarke Jul 21 '18 at 06:52
  • good question. The answer is, I'm learning bash and I want to really understand completely what's being piped, and how to pipe it. If this *should* work, I'd like to know how. If it *doesn't* work, I'd like to know why. I am in straight-up student mode here. – johnrubythecat Jul 21 '18 at 15:49
  • Fair enough. I'll point out that long pipelines of external programs can be difficult to maintain, debug, and adapt. Single line commands are rarely faster and can sometimes be slower because they encourage multiple child processes. Very often: simple is good. – cdarke Jul 22 '18 at 06:48

4 Answers4

1

Using zipgrep you can do this:

find . -name '*.ooutline' -print0 | xargs -0 zipgrep -Ho '.{0,20}$1.{0,20}'
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • I tested your command suggestion. It doesn't work. The *.ooutlline files (i.e. the zip files) contain .xml files, which are the files I'm really searching. FYI It's my understanding that there are many situations where zipgrep is preferred to zgrep, although I'm not sure of the details. zipgrep is just a shell script that does what I do above, so I chose to make it explicit. – johnrubythecat Jul 21 '18 at 15:46
0

Try with GNU Parallel like this, and use all your lovely Intel CPU cores in parallel:

find . -name \*.ooutline -print0 | parallel -0 --tag 'unzip -c {} | grep -Eo ".{0,20}"'

The --tag tags the output lines with the filenames. The {} represents the input filename.

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
0

I believe your original find command works fine, but you forgot to place it in a script file, say script.sh and then pass the string as command line argument? Here are the steps I took, let me know where I'm making the wrong assumptions:

Executed commands:

echo Alice Bob Peter >'Alice Bob Peter.txt'
echo Alice Alice Alice >'Alice Alice Alice.txt'
echo Alice Peter Bob >'Alice Peter Bob.txt'
for f in 'Alice Bob Peter.txt' 'Alice Alice Alice.txt' 'Alice Peter Bob.txt';do zip "${f%txt}ooutline" "$f";done
echo 'find . -name "*.ooutline" -print0 | xargs -0 -n1 unzip -c | grep  -m 10 -Eo ".{0,20}$1.{0,20}"' >script.sh
bash script.sh Peter

Output:

Archive:  ./Alice Peter Bob.ooutline
 extracting: Alice Peter Bob.txt     
Alice Peter Bob
chive:  ./Alice Bob Peter.ooutline
tracting: Alice Bob Peter.txt     
Alice Bob Peter
Johannes Riecken
  • 2,301
  • 16
  • 17
0

It sounds like you're just asking how to call unzip on each file found by find and have it's output piped to grep. Replacing unzip with cat for demonstration:

$ cat file
Wee, sleekit,
cowrin', tim'rous beastie,
Oh whit a panic's
in thy breastie

$ find . -maxdepth 1 -name file -exec sh -c 'cat "{}" | grep "whit"' \;
Oh whit a panic's

$ find . -maxdepth 1 -name file -exec cat "{}" \; | grep "whit"
Oh whit a panic's

$ find . -maxdepth 1 -name file -print0 | xargs -0 -I {} sh -c 'cat {} | grep "whit"'
Oh whit a panic's

$ find . -maxdepth 1 -name file -print0 | xargs -0 cat | grep "whit"
Oh whit a panic's

What's wrong with either of those? I can see you tried similar approaches and you seem to be saying there's some problem with them but you didn't provide sample input or expected output so we can't tell what the problem is. Try using a flat text file with cat instead of requiring a zip file with unzip so you can show a [mcve] in your question.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185