-1

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?

Mayukh Sarkar
  • 2,289
  • 1
  • 14
  • 38
  • 1
    What is `$i`? If you give a filename argument to `wc`, it doesn't use the piped stdin. – Barmar Aug 10 '21 at 06:44
  • Put `set -x` at the beginning of the script to see a trace of the execution. – Barmar Aug 10 '21 at 06:45
  • @Barmar No it is not a file. I found this in a SO post. Can you please tell me what shall be the command? – Mayukh Sarkar Aug 10 '21 at 06:46
  • If it's not a file, what is it? Where do you set that variable? Usually a variable named `i` is an iteration variable, e.g. `for i in *.txt` – Barmar Aug 10 '21 at 06:47
  • 2
    What SO post did you get it from? Don't just copy code without understanding how it works. – Barmar Aug 10 '21 at 06:48
  • @Barmar https://stackoverflow.com/questions/45767122/wc-does-not-return-an-integer-value-integer-expression-expected – Mayukh Sarkar Aug 10 '21 at 06:50
  • In that question, `$i` is the filename from the loop `for i in */*.$2`. Do you have a similar loop in your script? If not, why are you using `$i`? – Barmar Aug 10 '21 at 06:51
  • Just get rid of `"$i"` from your code. – Barmar Aug 10 '21 at 06:52

3 Answers3

2

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.

tripleee
  • 175,061
  • 34
  • 275
  • 318
1

-- 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
Ljm Dullaart
  • 4,273
  • 2
  • 14
  • 31
  • `$i` may expand to nothing and no argument, but `"$i"` will expand to an empty argument if the variable is empty. In C that would be a difference in `argc` and an extra `argv[2]` that points to a zero-length string (first byte is zero). – iBug Aug 10 '21 at 07:05
  • Except, that the first quote before the `$i` is a closing quote and the second quote after the `$i` is an opening quote. But I see your point. – Ljm Dullaart Aug 10 '21 at 07:10
  • @LjmDullaart The original quoting is correct (or would be if `$i` belonged there) -- the inside of `$( )` is a separate quoting context from the outside, so the quotes inside it match each other rather than the ones outside it. – Gordon Davisson Aug 10 '21 at 07:58
0

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.

Wiimm
  • 2,971
  • 1
  • 15
  • 25