2

I am trying to search for files that have pattern FW. From these filtered files I am trying to search for pattern chmod.*archive|archive.*chmod, then list them.

I tried with the below command, but it doesn't give me the desired output. Need help to get this issue sorted out.

find . -name '*FW*' -exec sh -c "cat {}|grep -iEq 'chmod.*archive|archive.*chmod'|ls" \;|more
Kusalananda
  • 333,661

3 Answers3

5

If I understand correctly, all you need is:

find . -type f -name '*FW*' -exec grep -iEq 'chmod.*archive|archive.*chmod' {} \; -ls

That will grep for your pattern in each file found by find, and if the grep is successful, will list the file in a format similar to ls -l.

Kusalananda
  • 333,661
terdon
  • 242,166
  • Thanks it seems to work....but need to understand how -ls is working at the end, does find command pipes the o/p to ls. – exp post Apr 02 '20 at 18:07
  • @AbdulWahabKhan no, this is -ls, it's an option for find (see man find). It has nothing to do with ls the command. – terdon Apr 02 '20 at 18:11
  • Thanks terdon...I have posted one more query ...in continuation to this post...please check, if this can be acheived....https://unix.stackexchange.com/questions/577555/piping-output-of-find-command – exp post Apr 02 '20 at 18:28
1

As an alternative to what @terdon proposed you could probably also use the following command:

grep -iErl 'chmod.*archive|archive.*chmod' . | grep FW

EDIT

As @Kusalananda has pointed out:

This would fail (give the wrong output) if you have matches in files located in directories that contain FW in their names.

Adjusting it to work properly makes it much less readable. The solution @terdon proposed is a more favorable option (also more efficient - see @tedron's comment).

Nevertheless here is a corrected version:

grep -iErl 'chmod.*archive|archive.*chmod' . | grep -E '[^/]*FW[^/]*$'

kurcze
  • 331
  • 1
    Nice! I suspect using find to locate the target files will be faster since grep needs to traverse the entire file before it can determine whether it has a match. But this should be more than find for few, small files, and is easier to write. – terdon Apr 02 '20 at 17:07
  • 1
    This would fail (give the wrong output) if you have matches in files located in directories that contain FW in their names. – Kusalananda Apr 02 '20 at 17:32
1

You have two options for getting the pathnames that corresponds to files that have lines that matches your pattern:

  1. Let find output the pathnames:

    find . -name '*FW*' -type f \
        -exec grep -q -i -e 'chmod.*archive' -e 'archive.*chmod' {} \; -print
    

    This runs grep on each found file individually, and then prints the pathnames for each file that contains matches for the pattern (which I, by the way, turned into a standard-compliant set of two separate basic regular expressions, since everything else in the answer was standard).

    This is probably what you would want to use if you want to do something else to the pathnames other than just printing them in the terminal (just add more -exec actions).

  2. Let grep output the pathnames:

    find . -name '*FW*' -type f \
        -exec grep -l -i -e 'chmod.*archive' -e 'archive.*chmod' {} +
    

    This runs grep on batches of found files. The grep utility will report the pathnames of each matching file given its -l ("dash-ell") option.

    This is likely to run quicker as it minimizes the number of grep invocations that are made, and would be what you would do if you just want to look at the pathnames.

Kusalananda
  • 333,661