-1

I have written a script to search an .ini file for some specific word.

The .ini file has one of two different names, (let's say config.ini or configuration.ini), so I have to check in both.

I am doing it with the following if sentences by using logical OR:

HAS_SOME_WORD=FALSE
if    [ "$(grep -v '^;\|^\[' "path_to_file/config.ini" | \
           grep -c '\\some_word')" -ge 1 ] \
   || [ "$(grep -v '^;\|^\[' "path_to_file/configuration.ini" | \          
          grep -c '\\some_word')" -ge 1 ]; then 
    HAS_SOME_WORD=TRUE
else
    HAS_SOME_WORD=FALSE
fi

I am avoiding the lines starting by ";" or "[" as they must not be included in the desired search, while looking for the word "\some_word".

I want is to exclude the grep error messages when one of the two files does not exist, i.e:

grep: path_to_file/config.ini: No such file or directory

or:

grep: path_to_file/configuration.ini: No such file or directory

I have been able to avoid them by redirecting the output to /dev/null when executing the script:

./search_script.sh 2>/dev/null

However I would like to include this redirection in the if code itself, not when invoking the script.

How shall I implement that? Is there a more efficient way of doing what I'm trying?

I have tried to add the -q parameter to grep in order to avoid the error messages printed, but it had no effect. Also tried adding 2>/dev/null redirection at the end of each if sentence, but I'm afraid that I haven't applied the correct syntax.

  • Adding a 2>/dev/null redirection in each if branch should work. Can you show us exactly what you tried? – JigglyNaga Jan 30 '17 at 17:15
  • @JigglyNaga I tried it as follows: if [ "$(grep -v '^;\|^\[' "path_to_file/config.ini" | \ grep -c '\\some_word')" -ge 1 2>/dev/null ]; then (For both if's) – Zumo de Vidrio Jan 31 '17 at 8:26
2

Since grep can search multiple files, and that -v and -c code can be simplified, try:

cd "path_to file"
if grep -qs '^[^;[].*\\some_word' config.ini configuration.ini ; then 
    # ...etc
fi
cd -

The grep options in long form:

grep --quiet --no-messages '^[^;[].*\\some_word' \
     config.ini configuration.ini 

The OP code -v (or --invert-match) and 2nd grep are needless, because a regexp like ^[^;[] can do it in one shot. From man grep:

A bracket expression is a list of characters enclosed by [ and ]. It matches any single character in that list; if the first character of the list is the caret ^ then it matches any character not in the list.

1

The other answer, suggesting --no-messages/-s, is more appropriate for your problem, but the following will also work for commands that don't have a "silent" option.

Redirecting the command

To redirect errors from a simple command, you should put the redirection with that command, ie. in the same position in the pipeline:

if [ "$(grep -v '^;\|^\[' "path_to_file/config.ini" 2>/dev/null | \
  grep -c '\\some_word')" -ge 1 ] \

The first grep is the one generating the "No such file or directory" message, so that's the one that has to be redirected.

Redirecting the pipeline

If multiple parts of the pipeline can generate errors, you could place the entire pipeline in a group, with a single redirection after it:

if [ "$( ( grep -v '^;\|^\[' "path_to_file/config.ini" | \
  grep -v -f "path_to_file/ignored_patterns" | \
  grep -c '\\some_word' )  2>/dev/null )" -ge 1 ] \

Redirecting the conditional construct

You can redirect the whole of the if construct by putting the redirection after the closing fi:

if [ "$(grep -v '^;\|^\[' "path_to_file/config.ini" | \
    grep -c '\\some_word')" -ge 1 ] \
 ...
else
 ...
fi 2>/dev/null

This will redirect errors from all commands (both test- and consequent-) inside that block.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.