O primeiro é um hack desajeitado, o segundo é um erro comum.
Esses dois testes fazem algo completamente diferente, o que produz o mesmo resultado.
if test ! $(which brew); then
Isso testa se a saída de which brew está vazia.
- Se
brewestiver no caminho de pesquisa, entãowhich brewproduzirá uma palavra de saída, portanto, o comandotestreceberá dois argumentos:!e o caminho parabrew. Quandotesttiver dois argumentos, o primeiro dos quais é!, retornará verdadeiro se o segundo argumento estiver vazio (o que não é o caso aqui) e, caso contrário, será falso. - Se
brewnão estiver no caminho de pesquisa, a saída dewhich brewestará vazia, portanto, o comandotestreceberá um único argumento que é!, portantotestretornará verdadeiro.
Observe que esse comando produzirá uma mensagem de erro e um status de falha se o caminho para brew contiver espaço em branco, porque é o que significa uma substituição de comando sem aspas . Acontece que um status de falha era o resultado desejado aqui, então isso funciona de maneira indireta.
Este comando não testa o código de saída de which brew . O código de saída é ignorado.
if ! which brew > /dev/null; then
Esta é a maneira direta de testar se which brew é bem-sucedido. Não depende de nada frágil, exceto which em si.
which brew é sempre chamado em ambos os casos. Por que seria importante que a saída fosse redirecionada para /dev/null ? "Ocultar a saída deste comando" não significa "não executar este comando".
A maneira correta de testar se brew não está disponível no caminho de pesquisa do comando é
if ! type brew >/dev/null 2>/dev/null; then