The -q flag for GNU grep is described as: `-q' `--quiet' `--silent' Quiet; do not write anything to standard output. Exit immediately with zero status if any match is found, even if an error was detected. Also see the `-s' or `--no-messages' option. `-s' `--no-messages' Suppress error messages about nonexistent or unreadable files. Portability note: unlike GNU `grep', traditional `grep' did not conform to POSIX.2, because traditional `grep' lacked a `-q' option and its `-s' option behaved like GNU `grep''s `-q' option. Shell scripts intended to be portable to traditional `grep' should avoid both `-q' and `-s' and should redirect output to `/dev/null' instead. Despite this, there are cases where the use of "grep" to find a string will succeed (with an exit status of 0), while an otherwise-identical search using "grep -q" will merely exit with a non-zero status code. While it's possible that I'm confused, that seems to contradict the above info excerpt. It's also possible that there's something peculiar about the FreeBSD environment (from the perspective of the GNU folks). How-To-Repeat: I encountered this in looking for certain pathnames in executables, thus: albert(8.3-P)[1] which grep /usr/bin/grep albert(8.3-P)[2] grep --version grep (GNU grep) 2.5.1-FreeBSD Copyright 1988, 1992-1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. albert(8.3-P)[3] grep -alw /usr/local /usr/local/bin/bison; echo $? /usr/local/bin/bison 0 albert(8.3-P)[4] strings -a /usr/local/bin/bison | grep -w /usr/local; echo $? /usr/local/lib /usr/local/share/locale /usr/local/share/bison /usr/local/bin/gm4 /usr/local/lib 0 albert(8.3-P)[5] strings -a /usr/local/bin/bison | grep -qw /usr/local ; echo $? 141 albert(8.3-P)[6] Most of the folks to whom I've shown this have agreed that 0 != 141. :-}
FreeBSD PR gnu/167009: > [strings -a /usr/local/bin/bison | grep -qw /usr/local fails] The peculiar thing is the shell, tcsh. What happens is that grep -q terminates early, so that strings receives SIGPIPE when it tries to write further data. Whereas the exit status of a pipeline in sh is always the exit status of the last element so that your command has the expected behaviour, this is different in tcsh. Tcsh looks backwards for a failing command if the last element has exit status 0, and returns the 141 corresponding to SIGPIPE. If you do not use -q, grep reads all of its input and strings will not be hit by SIGPIPE, so the exit status of the pipeline is the exit status of grep. Something similar happens if 'set -o pipefail' is in effect in bash or ksh93. I can't help but be happy that I'm not using tcsh, because tcsh -c 'yes | :' does return 0 (apparently it doesn't look backwards if the last element is a builtin) and tcsh -c 'yes | if (1) true' hangs. Also, the double prompt I see after typing yes | : in an interactive tcsh doesn't really inspire confidence. -- Jilles Tjoelker
Huh. Thanks for the explanation. :-} Peace, david -- David H. Wolfskill david@catwhisker.org Depriving a girl or boy of an opportunity for education is evil. See http://www.catwhisker.org/~david/publickey.gpg for my public key.
State Changed From-To: open->closed This is not a bug but a result of exit status of tcsh pipelines.
Responsible Changed From-To: freebsd-bugs->jilles Take.