Uma verificação alternativa, menos "limpa", mas mais próxima do que a pergunta tentou alcançar.
Lembre-se de que [ em seu núcleo é apenas um comando. Ele sempre aceita um número específico de parâmetros e sai com status de saída 0 (sucesso) ou 1 (falha), como todos os outros comandos. Por exemplo, quando você está comparando duas strings, a sintaxe é [ , string 1, == , string 2, ] .
Agora você está usando isso como a condição if :
[ prlctl list --info ubuntu-vm | grep State == "State: running" ]
Mas é ambíguo de várias maneiras. Como [ saberia que à esquerda você tem um comando para executar e não uma string fixa? Como saberia que o == é o operador de comparação de string, em vez de apenas um argumento para grep ? Como saberia que o | faz parte do valor da esquerda, em vez de separar o comando em [ prlctl list --info ubuntu-vm e grep State == "State: running" ] ?
Portanto, o lado esquerdo também precisa ser citado. Além disso, como você deseja comparar a saída desse comando, em vez dos mundos "prctl list --info ...", você precisa do operador $(…) :
[ "$(prlctl list --info ubuntu-vm | grep State)" == "State: running" ]