diff --git a/ShellCheck/Checks/Commands.hs b/ShellCheck/Checks/Commands.hs index 21a309e..dccd275 100644 --- a/ShellCheck/Checks/Commands.hs +++ b/ShellCheck/Checks/Commands.hs @@ -91,6 +91,7 @@ commandChecks = [ ,checkAliasesUsesArgs ,checkAliasesExpandEarly ,checkUnsetGlobs + ,checkFindWithoutPath ] buildCommandMap :: [CommandCheck] -> Map.Map CommandName (Token -> Analysis) @@ -599,5 +600,24 @@ checkUnsetGlobs = CommandCheck (Exactly "unset") (mapM_ check . arguments) warn (getId arg) 2184 "Quote arguments to unset so they're not glob expanded." +prop_checkFindWithoutPath1 = verify checkFindWithoutPath "find -type f" +prop_checkFindWithoutPath2 = verify checkFindWithoutPath "find" +prop_checkFindWithoutPath3 = verifyNot checkFindWithoutPath "find . -type f" +prop_checkFindWithoutPath4 = verifyNot checkFindWithoutPath "find -H -L \"$path\" -print" +checkFindWithoutPath = CommandCheck (Basename "find") f + where + f (T_SimpleCommand _ _ (cmd:args)) = + unless (hasPath args) $ + info (getId cmd) 2185 "Some finds don't have a default path. Specify '.' explicitly." + + -- This is a bit of a kludge. find supports flag arguments both before and after the path, + -- as well as multiple non-flag arguments that are not the path. We assume that all the + -- pre-path flags are single characters, which is generally the case. + hasPath (first:rest) = + let flag = fromJust $ getLiteralStringExt (const $ return "___") first in + not ("-" `isPrefixOf` flag) || length flag <= 2 && hasPath rest + hasPath [] = False + + return [] runTests = $( [| $(forAllProperties) (quickCheckWithResult (stdArgs { maxSuccess = 1 }) ) |])