conditional binary operator expected in shell script - shell

I was trying a simple program to compare the string values stored on a log file and was getting an error as below,
#!/bin/bash
check_val1="successful"
check_val2="completed"
log="/compile.log"
if [[ grep $check_val1 $log -ne $check_val1 || grep $check_val2 $log -ne $check_val2 ]];
then
echo "No Error"
else
echo "Error"
fi
Error:
./simple.sh: line 7: conditional binary operator expected
./simple.sh: line 7: syntax error near `$check_val1'
./simple.sh: line 7: `if [[ grep $check_val1 $log -ne $check_val1 || grep $check_val2 $log -ne $check_val2 ]];'

Problem is in your if [[...]] expression where you are using 2 grep commands without using command substitution i.e. $(grep 'pattern' file).
However instead of:
if [[ grep $check_val1 $log -ne $check_val1 || grep $check_val2 $log -ne $check_val2 ]]; then
You can use grep -q:
if grep -q -e "$check_val1" -e "$check_val2" "$log"; then
As per man grep:
-q, --quiet, --silent
Quiet mode: suppress normal output. grep will only search a file until a match
has been found, making searches potentially less expensive.

[[ trigers the test command. Test doesn't support testing the exit status of a command just by typing the command

Related

How to use wc -l integer output in a if statement

I am trying to execute the command git diff | grep pkg/client/clientset | wc -l and check if the output is more than 0 or not. I have the following script
if [ "$(git diff | grep pkg/client/clientset | wc -l "$i")" -gt "0" ]; then
echo "Hello"
fi
I am getting the following error while executing the script. The error I am getting is
line 29: [: : integer expression expected
Any idea of what can be going wrong?
Comparing the number of output lines to zero is almost always an antipattern. diff and grep both already tell you whether there was a difference (exit code 1) or a match (exit code 0) precisely so you can say
if diff old new; then
echo "There were differences"
fi
if git diff --exit-code; then
echo "There were differences"
fi
if git diff --exit-code pkg/client/clientset; then
echo "There were differences in this specific file"
fi
if git diff | grep -q pkg/client/clientset; then
echo "Hello"
fi
Notice that git diff requires an explicit option to enable this behavior.
-- EDIT --
There were some incorrect statements in the answer, pointed-out by commentators Gordon Davisson and iBug. They have been corrected in this version of the answer. The final conclusion (remove the "$i") remains the same though.
wc -l "$i" will count the lines in the file $i. If you never used i as a variable, then i will be empty and the command will be wc -l "". The output of that will be empty on STDOUT en contain wc: invalid zero-length file name on STDERR. If the variable i is used, wc will most likely complain about a non-existing file. The point is, that wc will not read STDIN.
I also made some incorrect statements about the quoting. As pointed out, between the ( and ), it is a different quoting context. This can be shown as follows:
$ a="$(/usr/bin/echo "hop")"
$ echo $a
hop
$ b=hop
$ a="$(/usr/bin/echo "$b")"
$ echo $a
hop
Just removing "$i" from the wc-l will solve your issue.
if [ "$(git diff | grep pkg/client/clientset | wc -l)" -gt "0" ]; then
echo "Hello"
fi
Only a note, that is to long for a comment:
if [ "$(git diff | grep pkg/client/clientset | wc -l "$i")" -gt "0" ]; then
I think you will test the existence of string pkg/client/clientset to enter the then part. In this case you can use:
if git diff | grep -q pkg/client/clientset; then
grep will only returns a status because option -q. The status is true after the first occurrence of the string. At this point grep stops. And this status is used by if.

How to match a folder name and use it in an if condition using grep in bash?

for d in */ ; do
cd $d
NUM = $(echo ${PWD##*/} | grep -q "*abc*");
if [[ "$NUM" -ne "0" ]]; then
pwd
fi
cd ..
done
Here I'm trying to match a folder name to some substring 'abc' in the name of the folder and check if the output of the grep is not 0. But it gives me an error which reads that NUM: command not found
An error was addressed in comments.
NUM = $(echo ${PWD##*/} | grep -q "*abc*"); should be NUM=$(echo ${PWD##*/} | grep -q "*abc*");.
To clarify, the core problem would be to be able to match current directory name to a pattern.
You can probably simply the code to just
if grep -q "*abc*" <<< "${PWD##*/}" 2>/dev/null; then
echo "$PWD"
# Your rest of the code goes here
fi
You can use the exit code of the grep directly in a if-conditional without using a temporary variable here ($NUM here). The condition will pass if grep was able to find a match. The here-string <<<, will pass the input to grep similar to echo with a pipeline. The part 2>/dev/null is to just suppress any errors (stderr - file descriptor 2) if grep throws!
As an additional requirement asked by OP, to negate the conditional check just do
if ! grep -q "*abc*" <<< "${PWD##*/}" 2>/dev/null; then

-bash: eval: line 109: unexpected EOF while looking for matching `"'

if [[ -s $GCMS_ENV && -r $GCMS_ENV ]]
then
echo "">/dev/null ##file exists
if [[ -s $GCMS_PRIV_ENV && -r $GCMS_PRIV_ENV ]]
then
egrep "[A-Z]?=.[a-zA-Z0-9]?" $GCMS_PRIV_ENV | grep -v ^# 2>/dev/null 1> $TMP_FILE
egrep "[A-Z]?=.[a-zA-Z0-9]?" $GCMS_ENV | grep -v ^# 2>/dev/null 1>> $TMP_FILE
else
egrep "[A-Z]?=.[a-zA-Z0-9]?" $GCMS_ENV | grep -v ^# 2>/dev/null 1> $TMP_FILE
fi
{
while read RECORD
do
VAR=$(echo $RECORD|cut -s -d$DELIM -f1)
VAL=$(echo $RECORD|cut -s -d$DELIM -f2-9)
eval export $VAR=$VAL
done
}<$TMP_FILE
else
echo "\n$THIS_FILE\n error:"
echo "The file $GCMS_ENV does not exist, no environment settings!"
return 1
fi
i am trying to run folllowing kSH shell in my linux box while running the same i am facing the following error.
-bash: eval: line 109: unexpected EOF while looking for matching `"'
-bash: eval: line 110: syntax error: unexpected end of file
please let me know anybody have a answer for the same
eval should be avoided whenever possible, especially when it is probably responsible for the syntax error you observe. Use this in place of your while loop.
while read -d"$DELIM" VAR VAL; do
declare -x "$VAR=$VAL"
done < "$TMP_FILE"
You may still have an error that eval triggered, so double check your input files to make sure the assignments have matched ".

Bash - output of command seems to be an integer but "[" complains

I am checking to see if a process on a remote server has been killed. The code I'm using is:
if [ `ssh -t -t -i id_dsa headless#remoteserver.com "ps -auxwww |grep pipeline| wc -l" | sed -e 's/^[ \t]*//'` -lt 3 ]
then
echo "PIPELINE STOPPED SUCCESSFULLY"
exit 0
else
echo "PIPELINE WAS NOT STOPPED SUCCESSFULLY"
exit 1
fi
However when I execute this I get:
: integer expression expected
PIPELINE WAS NOT STOPPED SUCCESSFULLY
1
The actual value returned is "1" with no whitespace. I checked that by:
vim <(ssh -t -t -i id_dsa headless#remoteserver.com "ps -auxwww |grep pipeline| wc -l" | sed -e 's/^[ \t]*//')
and then ":set list" which showed only the integer and a line feed as the returned value.
I'm at a loss here as to why this is not working.
If the output of the ssh command is truly just an integer preceded by optional tabs, then you shouldn't need the sed command; the shell will strip the leading and/or trailing whitespace as unnecessary before using it as an operand for the -lt operator.
if [ $(ssh -tti id_dsa headless#remoteserver.com "ps -auxwww | grep -c pipeline") -lt 3 ]; then
It is possible that result of the ssh is not the same when you run it manually as when it runs in the shell. You might try saving it in a variable so you can output it before testing it in your script:
result=$( ssh -tti id_dsa headless#remoteserver.com "ps -auxwww | grep -c pipeline" )
if [ $result -lt 3 ];
The return value you get is not entirely a digit. Maybe some shell-metacharacter/linefeed/whatever gets into your way here:
#!/bin/bash
var=$(ssh -t -t -i id_dsa headless#remoteserver.com "ps auxwww |grep -c pipeline")
echo $var
# just to prove my point here
# Remove all digits, and look wether there is a rest -> then its not integer
test -z "$var" -o -n "`echo $var | tr -d '[0-9]'`" && echo not-integer
# get out all the digits to use them for the arithmetic comparison
var2=$(grep -o "[0-9]" <<<"$var")
echo $var2
if [[ $var2 -lt 3 ]]
then
echo "PIPELINE STOPPED SUCCESSFULLY"
exit 0
else
echo "PIPELINE WAS NOT STOPPED SUCCESSFULLY"
exit 1
fi
As user mbratch noticed I was getting a "\r" in the returned value in addition to the expected "\n". So I changed my sed script so that it stripped out the "\r" instead of the whitespace (which chepner pointed out was unnecessary).
sed -e 's/\r*$//'

In a unix box, I am taking a list of files as input. If it is found, return the path otherwise return a message "filename file not found"

I have used the find command for this, but it doesnt return any message when a file is not found.
And I want the search to be recursive and return a message "not found" when a file is not found.
Here's the code I have done so far. Here "input.txt" contains the list of files to be searched.
set `cat input.txt`
echo $#
for i in $#
do
find $HOME -name $i
done
Try this:
listfile=input.txt
exec 3>&1
find | \
grep -f <( sed 's|.*|/&$|' "$listfile" ) | \
tee /dev/fd/3 | \
sed 's|.*/\([^/]*\)$|\1|' | \
grep -v -f - "$listfile" | \
sed 's/$/ Not found/'
exec 3>&-
open file descriptor 3
find the files
see if they're on the list (use sed to
send a copy of the found ones to file descriptor 3
strip off the directory name
get a list of the ones that don't appear
add the "Not found" message
close file descriptor 3
Output looks like:
/path/to/file1
/path/somewhere/file2
foo Not found
bar Not found
No loops necessary.
Whats wrong with using a script. I hope this will do.
#!/bin/bash -f
for i in $#
do
var=`find $HOME -name $i`
if [ -z "$var"]
then
var="File not found"
fi
echo $var
done
You can use the shell builtin 'test' to test the existence of a file. There is also an alternative syntax using square brackets:
if [ -f $a ]; then # Don't forget the semicolon.
echo $a
else
echo 'Not Found'
fi
Here is one way - create a list of all the files to grep against. If your implementation supports
grep -q otherwise use grep [pattern] 2&>1 >/dev/null....
find $HOME -type f |
while read fname
do
echo "$(basename $fname) $fname"
done > /tmp/chk.lis
while read fname
do
grep -q "^$fname" /tmp/chk.lis
[ $? -eq 0 ] && echo "$fname found" || echo "$fname not found"
done < /tmp/chk.lis
All of this is needed because POSIX find does not return an error when a file is not found
perl -nlE'say-f$_?$_:"not found: $_"' file

Resources