Reputation: 103
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
Upvotes: 1
Views: 491
Reputation: 158130
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"
Upvotes: 1
Reputation: 10133
A one-liner using GNU grep
and sed
:
grep -m1 -cw abc * | sed -E 's/:(.)$/ abc \1/'
Upvotes: 2
Reputation: 22301
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.
Upvotes: 2
Reputation: 189739
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.
Upvotes: 1