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.
2 Answers 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.
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.
You must log in to answer this question.
Explore related questions
See similar questions with these tags.
2>/dev/null
redirection in eachif
branch should work. Can you show us exactly what you tried?if [ "$(grep -v '^;\|^\[' "path_to_file/config.ini" | \ grep -c '\\some_word')" -ge 1 2>/dev/null ]; then
(For both if's)