Saturday, April 27, 2024
3
rated 0 times [  3] [ 0]  / answers: 1 / hits: 938  / 2 Years ago, tue, may 3, 2022, 11:24:25

I have the following three files


**file_01.sh**  
GOOD_word
bla bla BAD_word
miao GOOD_word bau
BAD_word
GOOD_word foo

**file_02.sh**  
GOOD_word yes
GOOD_word bla bla BAD_word
GOOD_word bla
BAD_word

**file_03.sh**  
just BAD_word
and bla bla

I would like to have the following result:


**“o_file.txt”:**  
./i_dir/file_01.sh:1:GOOD_word
./i_dir/file_01.sh:3:miao GOOD_word bau
./i_dir/file_01.sh:5:GOOD_word foo
./i_dir/file_02.sh:1:GOOD_word yes
./i_dir/file_02.sh:3:GOOD_word bla

This is what I try so far, but does not work.


find ./dir -type f -exec grep -E -i -H "GOOD_word" {} ; | 
grep -v “BAD_word” {} ; >> o_file.txt;

More From » command-line

 Answers
4

You are close - you just need to add -n for the line numbers and remove the second {} so that the grep -v operates on the output of the first grep, rather than on the found files:


$ find ./i_dir -type f -exec grep -E -i -H -n "GOOD_word" {} ; | grep -v "BAD_word"
./i_dir/file_01.sh:1:GOOD_word
./i_dir/file_01.sh:3:miao GOOD_word bau
./i_dir/file_01.sh:5:GOOD_word foo
./i_dir/file_02.sh:1:GOOD_word yes
./i_dir/file_02.sh:3:GOOD_word bla

I'm assuming that you need -E because your "real" GOOD_word is an extended regular expression - if that's not the case, you may omit it (and possibly also the -i flag).


Alternatively, you could do something like this, using bash globstar for the directory descent and awk for the logic:


shopt -s globstar
awk '/GOOD_word/ && !/BAD_word/{print FILENAME,FNR,$0}' OFS=: ./i_dir/**/*

See also



[#2250] Wednesday, May 4, 2022, 2 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
izecaptur

Total Points: 113
Total Questions: 102
Total Answers: 114

Location: Northern Mariana Islands
Member since Fri, Jan 15, 2021
3 Years ago
;