1

I have a directory with some files. I want to know if a word exists in each file. $1 is my directory that I give it as a parameter

e.g. ./myscript.sh /mnt/c/User/er/Desktop/shows

I have written this code but the terminal shows this error : [: it21754 :binary operator expected

#!/bin/bash
for a in $( find "$1" -type f )
do
      if[ egrep 'it21754' $a ]
      then 
          echo "0" 
      else 
          echo "1"
      fi 
done
GAD3R
  • 66,769
  • 1
    It's not entirely clear what behavior you're looking for. Do you really want to output a 0 or 1 for every file in the directory? Once you fix the error and this is successful, you will get a series of 0s and 1s, and it won't be immediately obvious which files contain the word you're looking for. If you could describe your desired output, you'll be more likely to get a helpful answer. – De Novo Dec 11 '18 at 19:39

1 Answers1

4

Don't loop over the output of find. It's rather inelegant as the complete find command has to finish and produce all its output before the loop can even run its first iteration. Furthermore you disqualify your script from working correctly with filenames that contain spaces. The result of the command substitution would be split on spaces to produce words for the loop to loop over.

Instead, let the find command generate filenames for the loop like this:

find "$1" -type f -exec sh -c '...loop here...' sh {} +

We'll come back to this shortly.

The syntax on the line

if[ egrep 'it21754' $a ]

is a bit wonky, and you definitely do not need egrep here (grep is enough).

By "wonky" I mean that a [ ... ] test usually looks like [ op arg ] or [ arg op arg ] where op is some operator like -f or -eq or = and arg is a string. You use egrep and it21754 and whatever $a expands to, which is what generates the error that you get. You can't run egrep in this context really, and you don't need to.

The correct if-statement is

if grep -qwF 'it21754' "$a"; then
    echo 0
else
    echo 1
fi

The -qwF flags makes grep quiet (-q), it makes it match using string comparisons rather than regular expressions (-F), and it assures that the string matched will be a complete word rather than a substring (-w). Here we use the exit status of grep to choose whether to output a 0 (for a match) or 1 (for no match).

I've also double quoted $a as "$a" just in case the filename contains any spaces or filename globbing characters.

Interestingly enough, those are the numbers that grep uses for its exit status anyway, so we could shorten the whole thing to just

grep -qwF 'it21754' "$a"
echo "$?"

The $? variable holds the exit status of the most recently executed command.

Plugging that into our find command, we get

find "$1" -type f -exec sh -c '
    for a do
        grep -qwF "it21754" "$a"
        echo "$?"
    done' sh {} +

This will produce a number of ones and zeroes depending on whether the files contain the given word or not. However, I think you may be looking for the filenames of the files that contain the word rather than a zero or a one. For that we may use

find "$1" -type f -exec grep -lwF 'it21754' {} +

Here, I've changed the -q to a -l ("dash ell"). This calls grep with the found files and grep will only output the filenames of the ones that contains the given word. We don't need the sh -c bit any longer since we're calling a single utility (not grep and echo).

Of course, you could do the same thing with just grep:

grep -R -lwF 'it21754' "$1"

With -R, grep will search the subdirectories given on the command line recursively.

It may be worth noting that the -w and -R flags of grep are not standard, but implemented by the most common grep variants.

Related:

Kusalananda
  • 333,661
  • re: grep is enough, it looks like the OP is actually looking for a literal match, rather than a pattern match, so even fgrep is enough. – De Novo Dec 11 '18 at 20:03
  • @DeNovo This is what the last command does. grep -F is equivalent to fgrep. – Kusalananda Dec 11 '18 at 20:12
  • Ahh yes, I see you used the -F flag now. I had just skimmed to see if there was any need for me to hit submit on the answer I was working on. You may want to clarify that by "the [ egrep 'it21754' $a ] syntax is wonky", you mean that is what is throwing the error. There's a lot of text in this (excellent) answer. It may be helpful to call attention to the command that is throwing the error. – De Novo Dec 11 '18 at 20:21
  • 1
    @DeNovo Thanks. I will expand on the "wonky" bit. – Kusalananda Dec 11 '18 at 21:00