macosgrephomebrewzsh

Zsh | `brew list | {any command}` raises uncaught signal PIPE error


On an MacOS Big Sur machine, running a zsh console running the following command:

brew list | grep -q some-library

raises the following error:

Error: Failure while executing; `ls /usr/local/Cellar` was terminated by uncaught signal PIPE.

Running the same command on a Mojave macbook does not yield an error. This appears to happen with any brew list | {command} as the following also raises the error:

brew list | echo 'hi' 

I've restored my brew incase something was broken but that has not changed anything. Any ideas as to why I am seeing this error?

Update: This appears to be happening due in zsh consoles


Solution

  • When a program tries to write to a pipe after the read end of the pipe has been closed, the program receives a SIGPIPE signal, which terminates the program unless it catches the signal (which few do).

    Shells and other applications that execute commands will often suppress the termination message in this case, because it's common that pipeline readers exit before consuming all their standard input. But apparently the version of brew in Big Sur reports this termination status.

    In this case, grep -q exits as soon as it reads a matching line. Since it's not printing anything, it knows that it has a successful match at the first match, and doesn't need to keep reading.

    You can suppress it by adding another command to consume any remaining data in the pipe.

    brew list | { grep -q some-library; cat > /dev/null; }
    

    The only problem with this is if you were using grep -q to get its exit status, this has been overwritten by the status of cat. You can work around this by saving $?:

    brew list | (grep -q somelib; ret=$?; cat >/dev/null; exit $ret)