If, else based on command piped to grep

I can't figure out how to make this (what supposed to be simple) script to work. Basically what I want, to run different stuff based on the state of my Parallels vm, something like this:

if [ prlctl list --info ubuntu-vm | grep State == "State: running" ] ; then 
   echo 'machine is running'
else
   echo 'machine is not running'
fi

Of course that doesn't work


The problem is that you are putting it all within [, i.e. the test command. Moreover, your usage of grep is broken.

All you need is:

if prlctl list --info ubuntu-vm | grep -q "State: running"; then
   echo 'machine is running'
else
   echo 'machine is not running'
fi

Note the usage of -q as an argument to grep. It doesn't write anything to STDOUT and exits with a status of 0 if the match is found, and non-zero otherwise.


An alternative check, less "clean" but closer to what the question tried to achieve.

Remember that [ at its core is just a command. It always accepts a specific number of parameters, and exits with either 0 (success) or 1 (failure) exit status, as all other commands do. For example, when you're comparing two strings, the syntax is[, string 1, ==, string 2, ].

Right now you're using this as the if condition:

[ prlctl list --info ubuntu-vm | grep State == "State: running" ]

But it's ambiguous in several ways. How would [ know that on the left you have a command to run and not a fixed string? How would it know that the == is the string comparison operator, rather than just an argument to grep? How would it know that the | is part of the left-hand value, rather than separating the command into [ prlctl list --info ubuntu-vm and grep State == "State: running" ]?

So the left side needs to be quoted as well. Also, since you want to compare the output of that command, rather than the worlds "prctl list --info..." themselves, you need the $(…) operator:

[ "$(prlctl list --info ubuntu-vm | grep State)" == "State: running" ]