@@ -408,6 +408,9 @@ prop_checkGrepQPipefail2 = verify checkGrepQPipefail "set -o pipefail; cat file
408408prop_checkGrepQPipefail3 = verify checkGrepQPipefail " set -o pipefail; cat file | grep -iq pattern"
409409prop_checkGrepQPipefail4 = verify checkGrepQPipefail " set -o pipefail; cmd1 | cmd2 | grep -q pattern"
410410prop_checkGrepQPipefail5 = verify checkGrepQPipefail " set -euo pipefail; cmd | grep -q foo"
411+ prop_checkGrepQPipefail6 = verify checkGrepQPipefail " set -o pipefail; cmd | grep -m 2 foo | cmd2"
412+ prop_checkGrepQPipefail7 = verify checkGrepQPipefail " set -o pipefail; cmd | grep -L foo | cmd2"
413+
411414prop_checkGrepQPipefailN1 = verifyNot checkGrepQPipefail " cat file | grep -q pattern"
412415prop_checkGrepQPipefailN2 = verifyNot checkGrepQPipefail " set -o pipefail; grep -q pattern file"
413416prop_checkGrepQPipefailN3 = verifyNot checkGrepQPipefail " set -o pipefail; cat file | grep pattern"
@@ -427,18 +430,25 @@ checkEgrepQPipefail = CommandCheck (Basename "egrep") checkQuietGrepInPipefailIm
427430prop_checkFgrepQPipefail1 = verify checkFgrepQPipefail " set -o pipefail; cat file | fgrep -q pattern"
428431checkFgrepQPipefail = CommandCheck (Basename " fgrep" ) checkQuietGrepInPipefailImpl
429432
433+ -- Catches occurrences of "grep -q" and variants inside of pipes under pipefail.
430434checkQuietGrepInPipefailImpl cmd = do
431435 pipefail <- asks hasPipefail
432436 astPath <- getPathM cmd
433437 sequence_ $ do
434438 guard pipefail
435- opts <- parseGrepOpts $ arguments cmd
436- guard $ any ( \ (flag, _) -> flag == " q " || flag == " quiet " ) opts
439+ opts <- map fst <$> parseGrepOpts ( arguments cmd)
440+ guard $ any isEarlyExitFlag opts
437441 _simpleCmd: grepRedirectingCmd: parentNodes <- Just $ NE. toList astPath
438442 T_Pipeline _ _ (_first: redirectingCmds) <- listToMaybe parentNodes
439443 guard $ any (\ node -> getId node == getId grepRedirectingCmd) redirectingCmds
440444 return $ warn (getId cmd) 2337 warnMsg
441445 where
446+ -- Contains "L", even though BSD grep does not exit early with this flag,
447+ -- but GNU grep does. This is consistent with the linter practice of warning
448+ -- about potential problems, while also allowing users to disable specific
449+ -- linter checks locally.
450+ earlyExitFlags = [" q" , " quiet" , " m" , " max-count" , " L" ]
451+ isEarlyExitFlag name = name `elem` earlyExitFlags
442452 parseGrepOpts = getOpts (True , True )
443453 " cilLnoqsvwxhHrRbaEFGPe:f:m:A:B:C:d:D:"
444454 (map (\ name -> (name, True )) longOptionsConsumingParameter)
0 commit comments