1

I am trying to check if items in an array options are in a file $file using the following simplified code:

options=(
    A
    B
    C
)

for i in "${options[@]}"; do
    if grep -F $file "${i}" = false; then
        echo "${i}"
    fi
done

I expect this to output A, B, or C if they are not present in $file, but instead it outputs for A, B, and C:

grep: A: No such file or directory
grep: =: No such file or directory
grep: false: No such file or directory

From this, it seems that grep is interpreting all arguments as files to either check or check with, which also implies that the boolean in the if statement does not have the correct syntax. So my question is twofold:

  1. How can I use grep or another command to check if an element in the array is in $file?
  2. How can I prevent this command from interpreting the boolean as an argument instead of leaving it as part of the if statement?

2 Answers 2

0
  1. Quote all your variable expansions, including $file.
  2. You are not supposed to check "booleans". In the shell, there is no such thing. You mean to check the exit code of grep, that is 1 if no line was matched and 0 if a line was matched (you can find it in man grep).
  3. Check the order of grep arguments. First comes the pattern, then the file name.

This will echo all elements in the array options that are not in the file:

options=(
    A
    B
    C
)

for i in "${options[@]}"; do
    if ! grep -qF "$i" "$file"; then
        echo "$i"
    fi
done

I added -q flag to grep, which suppresses the lines grep matches and that otherwise would be sent to stdout.

2
  • Apologies, the items in the array are directories and I missed that in the code cleanup. The solution seems to work perfectly, thanks a million! The name of the file does not contain any spaces so I thought the quotation marks were unnecesary. Is it still recommended to add them?
    – Fergus
    Commented Jun 12, 2020 at 0:30
  • Edited my answer accordingly. You're welcome, glad to help! If no spaces in the filenames nor special characters (e.g. *), that would be OK, but better safe than sorry ;)
    – Quasímodo
    Commented Jun 12, 2020 at 0:54
0
Usage: grep [OPTION]... PATTERN [FILE]...                                                                                                                          
Search for PATTERN in each FILE.                                                                                                                                   
Example: grep -i 'hello world' menu.h main.c   

-q, --quiet, --silent     suppress all normal output

options=(
    A
    B
    C
)

for i in "${options[@]}"; do
    if grep -q "${i}" $file; then
        echo "${i}" # ${i##*/} is a parametr expansion 
                    #it removes left side of string till last slash
    fi
done
2
  • Apologies, the items in the array are directories and I missed that in the code cleanup. Your solution outputs the string if it is contained in $file, not if it isn't. Thanks for the help anyway.
    – Fergus
    Commented Jun 12, 2020 at 0:34
  • you didn't mention that (maybe i had to figure it out from the '= false' but as it's not usual my mind ignored it quickly) anyhow its not a big deal use "!" symbole to invert any test command ! true == false , ! false == true other than that for any command use command --help and man command to know how to use it .
    – Yunus
    Commented Jun 12, 2020 at 0:46

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.