1

I have multiple files inside a folder and I want to scan the contents of each file to check for a string e.g. "abc" (case sensitive). I want to output the file name as well as the string with a label like 1 or 0 to tell if the string was present or not. E.g. if there are files

A1
A2
B3
B5
C8
Z7

and only B3 and C8 contain "abc" . The output should be as follows

A1 abc 0
A2 abc 0
B3 abc 1
B5 abc 0
C8 abc 1
Z7 abc 0

All this should be printed into a "output.txt" file.

My code seems to work :

#!/bin/bash
touch output.txt
for f in * ; 
do echo ${f} ;
 echo "abc" ;
 grep -w "abc" ${f}| wc -l ;
done

The output is like

A1 
abc 
0
A2 
abc 
0
B3 
abc 
1
B5 
abc 
0
C8 
abc 
1
Z7 
abc 
0

However, I am unable to print them into the txt file, also not able to do it in the order I want. Kindly advise.

Edit : I cd into the directory containing the files and the txt file is in an outside root directory.

Edit 2 : This is not similar to "echo -n" prints "-n" as, I want to use grep to print out file names while simultaneously adding labels depending on the presence/absence of a particular string

2014GAM
  • 103
  • 1
  • 9
  • What do you mean *in the order I want*? The output from your program seems in order. – oguz ismail Feb 26 '21 at 06:10
  • Does this answer your question? ['echo' without newline in a shell script](https://stackoverflow.com/questions/11193466/echo-without-newline-in-a-shell-script) – dahiya_boy Feb 26 '21 at 06:12
  • @ oguz ismail : even if it is in order, I am unable to print the output into a txt file – 2014GAM Feb 26 '21 at 06:18
  • Yeah, you need `done > output.txt` for that. Though I'd prefer the awk program tripleee posted below. – oguz ismail Feb 26 '21 at 06:20

4 Answers4

2

A one-liner using GNU grep and sed:

grep -m1 -cw abc * | sed -E 's/:(.)$/ abc \1/'
M. Nejat Aydin
  • 9,597
  • 1
  • 7
  • 17
2

I would do it like this:

word=abc
for f in *
do
  grep -vqswF "$word" "$f"
  label=$?
  echo "$f $word $label"
done

-v makes the exit code of grep to be 1 if the word is not in the file, 0 if it is. -q ensures that grep does not output anything to stdout. In my example, I also used -s which supresses error messages from unreadable files. You don't have to use this, but errors like this will show up in the exit code (usually 2 in such a case). -F ensures that your code will still work if you set the word to something containing special characters for grep.

user1934428
  • 19,864
  • 7
  • 42
  • 87
1

If you have a single string, grep -l could do what you want with a bit of postprocessing, but the most straightforward solution will be Awk.

awk -v str="abc" 'FNR == 1 {
    if (!p) print f, str, 0; f = FILENAME; p=0 }
0 ~ str { print f, str, 1; p = 1; nextfile }
END { if (!p) print f, str, 0 }' * >output.txt

Recall that Awk processes the entire script for each input line and evaluates the conditions. FNR, the input line number, is 1 when you start processing a new fils, we check if there is data from a previous file which needs to be printed, then initialize a couple of variables for the current file. If we see the search string, we print and close the current file. When we reach the end of all files, chech again if something from the last file still needs to be printed.

tripleee
  • 175,061
  • 34
  • 275
  • 318
1

You can use find and grep:

find -maxdepth 1 -type f  -printf "%p abc " \
     -exec grep -q abc {} \; -printf "1\n" -o -printf "0\n"
hek2mgl
  • 152,036
  • 28
  • 249
  • 266