Write a shell script that find-greps and outputs f

2020-07-22 18:00发布

问题:

To see all the php files that contain "abc" I can use this simple script:

find . -name "*php" -exec grep -l abc {} \;

I can omit the -l and i get extracted some part of the content instead of the filenames as results:

find . -name "*php" -exec grep abc {} \;

What I would like now is a version that does both at the same time, but on the same line.

Expected output:

path1/filename1: lorem abc ipsum
path2/filename2: ipsum abc lorem
path3/filename3: non abc quod

More or less like grep abc * does.

Edit: I want to use this as a simple shell script. It would be great if the output is on one line, so further grepping would be possible. But it is not necessary that the script is only one line, i am putting it in a bash script file anyways.

Edit 2: Later I found "ack", which is a great tool and I use this now in most cases instead of grep. It does all this and more. http://betterthangrep.com/ You would write ack --php --nogroup abc to get the desired result

回答1:

Use the -H switch (man grep):

find . -name "*php" -exec grep -H abc {} \;

Alternative using xargs (now the -H switch is not needed, at least for the version of grep I have here):

find . -name "*php" -print | xargs grep abc

Edit: As a consequence of grep's behavior as noted by orsogufo, the second command above should use -H if find could conceivably return only a single filename (i.e. if there is only a single PHP file). If orsogufo's comment w.r.t. -print0 is also incorporated, the command becomes:

find . -name "*php" -print0 | xargs -0 grep -H abc

Edit 2: A (more1) POSIX compliant version as proposed by Jonathan Leffler, which through the use of /dev/null avoids the -H switch:

find . -name "*php" -print0 | xargs -0 grep abc /dev/null

1: A quote from the opengroup.org manual on find hints that -print0 is non-standard:

A feature of SVR4's find utility was the -exec primary's + terminator. This allowed filenames containing special characters (especially s) to be grouped together without the problems that occur if such filenames are piped to xargs. Other implementations have added other ways to get around this problem, notably a -print0 primary that wrote filenames with a null byte terminator. This was considered here, but not adopted. Using a null terminator meant that any utility that was going to process find's -print0 output had to add a new option to parse the null terminators it would now be reading.



回答2:

If you don't need to recursively search, you can just do..

grep -H abc *.php

..which gives you the desired output. -H is the default behaviour (at least on the OS X version of grep), so you can omit this:

grep abc *.php

You can grep recursively using the -R flag, but you're unable limit it to .php files:

grep -R abc *

Again, this has the same desired output.

I know this doesn't exactly answer your questions, it's just.. an alternative... The above are just grep with a single flag, so are easier to remember than find/-exec/grep/xargs combinations! (irrelevant for a script, but useful for day-to-day shell'ing)



回答3:

find /path -type f -name "*.php" | awk '
{
    while((getline line<$0)>0){
        if(line ~ /time/){
            print $0":"line
            #do some other things here
        }
    }    
}'