mirror of
https://github.com/koalaman/shellcheck.git
synced 2025-09-30 00:39:19 +08:00
Compare commits
14 Commits
dependabot
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
1553dba6af | ||
|
aa07ba0d2a | ||
|
6a876f0b48 | ||
|
8c616761fa | ||
|
94ded2db74 | ||
|
a0716497fb | ||
|
b23c013549 | ||
|
32cae7a1c5 | ||
|
5de0448a72 | ||
|
6d4fa9fb2c | ||
|
14aac627f4 | ||
|
aea67a4532 | ||
|
da12ce67f5 | ||
|
fce4bc8352 |
27
.github/ISSUE_TEMPLATE.md
vendored
27
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,27 +0,0 @@
|
|||||||
#### For bugs
|
|
||||||
- Rule Id (if any, e.g. SC1000):
|
|
||||||
- My shellcheck version (`shellcheck --version` or "online"):
|
|
||||||
- [ ] The rule's wiki page does not already cover this (e.g. https://shellcheck.net/wiki/SC2086)
|
|
||||||
- [ ] I tried on https://www.shellcheck.net/ and verified that this is still a problem on the latest commit
|
|
||||||
|
|
||||||
#### For new checks and feature suggestions
|
|
||||||
- [ ] https://www.shellcheck.net/ (i.e. the latest commit) currently gives no useful warnings about this
|
|
||||||
- [ ] I searched through https://github.com/koalaman/shellcheck/issues and didn't find anything related
|
|
||||||
|
|
||||||
|
|
||||||
#### Here's a snippet or screenshot that shows the problem:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
|
|
||||||
#!/your/interpreter
|
|
||||||
your script here
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Here's what shellcheck currently says:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### Here's what I wanted or expected to see:
|
|
||||||
|
|
||||||
|
|
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@@ -48,7 +48,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
uses: actions/download-artifact@v5
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
@@ -77,7 +77,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
uses: actions/download-artifact@v5
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
- name: Build source
|
- name: Build source
|
||||||
run: |
|
run: |
|
||||||
@@ -100,7 +100,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
uses: actions/download-artifact@v5
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
- name: Work around GitHub permissions bug
|
- name: Work around GitHub permissions bug
|
||||||
run: chmod +x *.bin/*/shellcheck*
|
run: chmod +x *.bin/*/shellcheck*
|
||||||
@@ -135,7 +135,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
uses: actions/download-artifact@v5
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
- name: Upload to GitHub
|
- name: Upload to GitHub
|
||||||
env:
|
env:
|
||||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@@ -14,6 +14,7 @@ cabal.sandbox.config
|
|||||||
cabal.config
|
cabal.config
|
||||||
cabal.project.freeze
|
cabal.project.freeze
|
||||||
.stack-work
|
.stack-work
|
||||||
|
stack.yaml.lock
|
||||||
|
|
||||||
### Snap ###
|
### Snap ###
|
||||||
/snap/.snapcraft/
|
/snap/.snapcraft/
|
||||||
@@ -22,3 +23,6 @@ cabal.project.freeze
|
|||||||
/prime/
|
/prime/
|
||||||
*.snap
|
*.snap
|
||||||
/dist-newstyle/
|
/dist-newstyle/
|
||||||
|
|
||||||
|
### misc ###
|
||||||
|
/shellcheck.1
|
||||||
|
@@ -2349,6 +2349,8 @@ prop_checkFunctionsUsedExternally8 =
|
|||||||
verifyTree checkFunctionsUsedExternally "foo() { :; }; command sudo foo"
|
verifyTree checkFunctionsUsedExternally "foo() { :; }; command sudo foo"
|
||||||
prop_checkFunctionsUsedExternally9 =
|
prop_checkFunctionsUsedExternally9 =
|
||||||
verifyTree checkFunctionsUsedExternally "foo() { :; }; exec -c doas foo"
|
verifyTree checkFunctionsUsedExternally "foo() { :; }; exec -c doas foo"
|
||||||
|
prop_checkFunctionsUsedExternally10 =
|
||||||
|
verifyTree checkFunctionsUsedExternally "foo() { :; }; timeout -p 10 foo"
|
||||||
checkFunctionsUsedExternally params t =
|
checkFunctionsUsedExternally params t =
|
||||||
runNodeAnalysis checkCommand params t
|
runNodeAnalysis checkCommand params t
|
||||||
where
|
where
|
||||||
@@ -2376,6 +2378,7 @@ checkFunctionsUsedExternally params t =
|
|||||||
"run0" -> firstNonFlag
|
"run0" -> firstNonFlag
|
||||||
"xargs" -> firstNonFlag
|
"xargs" -> firstNonFlag
|
||||||
"tmux" -> firstNonFlag
|
"tmux" -> firstNonFlag
|
||||||
|
"timeout" -> take 1 $ drop 1 $ dropFlags argAndString
|
||||||
"ssh" -> take 1 $ drop 1 $ dropFlags argAndString
|
"ssh" -> take 1 $ drop 1 $ dropFlags argAndString
|
||||||
"find" -> take 1 $ drop 1 $
|
"find" -> take 1 $ drop 1 $
|
||||||
dropWhile (\x -> fst x `notElem` findExecFlags) argAndString
|
dropWhile (\x -> fst x `notElem` findExecFlags) argAndString
|
||||||
|
@@ -224,9 +224,9 @@ makeParameters spec = params
|
|||||||
hasPipefail =
|
hasPipefail =
|
||||||
case shellType params of
|
case shellType params of
|
||||||
Bash -> isOptionSet "pipefail" root
|
Bash -> isOptionSet "pipefail" root
|
||||||
Dash -> True
|
Dash -> isOptionSet "pipefail" root
|
||||||
BusyboxSh -> isOptionSet "pipefail" root
|
BusyboxSh -> isOptionSet "pipefail" root
|
||||||
Sh -> True
|
Sh -> isOptionSet "pipefail" root
|
||||||
Ksh -> isOptionSet "pipefail" root,
|
Ksh -> isOptionSet "pipefail" root,
|
||||||
hasExecfail =
|
hasExecfail =
|
||||||
case shellType params of
|
case shellType params of
|
||||||
|
@@ -148,8 +148,8 @@ prop_checkBashisms53 = verifyNot checkBashisms "#!/bin/sh\nprintf -- -f\n"
|
|||||||
prop_checkBashisms54 = verify checkBashisms "#!/bin/sh\nfoo+=bar"
|
prop_checkBashisms54 = verify checkBashisms "#!/bin/sh\nfoo+=bar"
|
||||||
prop_checkBashisms55 = verify checkBashisms "#!/bin/sh\necho ${@%foo}"
|
prop_checkBashisms55 = verify checkBashisms "#!/bin/sh\necho ${@%foo}"
|
||||||
prop_checkBashisms56 = verifyNot checkBashisms "#!/bin/sh\necho ${##}"
|
prop_checkBashisms56 = verifyNot checkBashisms "#!/bin/sh\necho ${##}"
|
||||||
prop_checkBashisms57 = verifyNot checkBashisms "#!/bin/dash\nulimit -c 0"
|
prop_checkBashisms57 = verifyNot checkBashisms "#!/bin/dash\nulimit -m unlimited"
|
||||||
prop_checkBashisms58 = verify checkBashisms "#!/bin/sh\nulimit -c 0"
|
prop_checkBashisms58 = verify checkBashisms "#!/bin/sh\nulimit -x unlimited"
|
||||||
prop_checkBashisms59 = verify checkBashisms "#!/bin/sh\njobs -s"
|
prop_checkBashisms59 = verify checkBashisms "#!/bin/sh\njobs -s"
|
||||||
prop_checkBashisms60 = verifyNot checkBashisms "#!/bin/sh\njobs -p"
|
prop_checkBashisms60 = verifyNot checkBashisms "#!/bin/sh\njobs -p"
|
||||||
prop_checkBashisms61 = verifyNot checkBashisms "#!/bin/sh\njobs -lp"
|
prop_checkBashisms61 = verifyNot checkBashisms "#!/bin/sh\njobs -lp"
|
||||||
@@ -175,7 +175,7 @@ prop_checkBashisms80 = verifyNot checkBashisms "#!/bin/sh\nhash -r"
|
|||||||
prop_checkBashisms81 = verifyNot checkBashisms "#!/bin/dash\nhash -v"
|
prop_checkBashisms81 = verifyNot checkBashisms "#!/bin/dash\nhash -v"
|
||||||
prop_checkBashisms82 = verifyNot checkBashisms "#!/bin/sh\nset -v +o allexport -o errexit -C"
|
prop_checkBashisms82 = verifyNot checkBashisms "#!/bin/sh\nset -v +o allexport -o errexit -C"
|
||||||
prop_checkBashisms83 = verifyNot checkBashisms "#!/bin/sh\nset --"
|
prop_checkBashisms83 = verifyNot checkBashisms "#!/bin/sh\nset --"
|
||||||
prop_checkBashisms84 = verify checkBashisms "#!/bin/sh\nset -o pipefail"
|
prop_checkBashisms84 = verifyNot checkBashisms "#!/bin/sh\nset -o pipefail"
|
||||||
prop_checkBashisms85 = verify checkBashisms "#!/bin/sh\nset -B"
|
prop_checkBashisms85 = verify checkBashisms "#!/bin/sh\nset -B"
|
||||||
prop_checkBashisms86 = verifyNot checkBashisms "#!/bin/dash\nset -o emacs"
|
prop_checkBashisms86 = verifyNot checkBashisms "#!/bin/dash\nset -o emacs"
|
||||||
prop_checkBashisms87 = verify checkBashisms "#!/bin/sh\nset -o emacs"
|
prop_checkBashisms87 = verify checkBashisms "#!/bin/sh\nset -o emacs"
|
||||||
@@ -383,8 +383,8 @@ checkBashisms = ForShell [Sh, Dash, BusyboxSh] $ \t -> do
|
|||||||
beginsWithDoubleDash = (`matches` mkRegex "^--.+$")
|
beginsWithDoubleDash = (`matches` mkRegex "^--.+$")
|
||||||
longOptions = Set.fromList
|
longOptions = Set.fromList
|
||||||
[ "allexport", "errexit", "ignoreeof", "monitor", "noclobber"
|
[ "allexport", "errexit", "ignoreeof", "monitor", "noclobber"
|
||||||
, "noexec", "noglob", "nolog", "notify" , "nounset", "verbose"
|
, "noexec", "noglob", "nolog", "notify" , "nounset", "pipefail"
|
||||||
, "vi", "xtrace" ]
|
, "verbose", "vi", "xtrace" ]
|
||||||
|
|
||||||
bashism t@(T_SimpleCommand id _ (cmd:rest)) =
|
bashism t@(T_SimpleCommand id _ (cmd:rest)) =
|
||||||
let name = fromMaybe "" $ getCommandName t
|
let name = fromMaybe "" $ getCommandName t
|
||||||
@@ -446,7 +446,12 @@ checkBashisms = ForShell [Sh, Dash, BusyboxSh] $ \t -> do
|
|||||||
("readonly", Just ["p"]),
|
("readonly", Just ["p"]),
|
||||||
("trap", Just []),
|
("trap", Just []),
|
||||||
("type", Just $ if isBusyboxSh then ["p"] else []),
|
("type", Just $ if isBusyboxSh then ["p"] else []),
|
||||||
("ulimit", if isDash then Nothing else Just ["f"]),
|
("ulimit",
|
||||||
|
Just $
|
||||||
|
if isDash
|
||||||
|
then ["H", "S", "a", "c", "d", "f", "l", "m", "n", "p", "r", "s", "t", "v", "w"]
|
||||||
|
else ["H", "S", "a", "c", "d", "f", "n", "s", "t", "v"] -- POSIX.1-2024
|
||||||
|
),
|
||||||
("umask", Just ["S"]),
|
("umask", Just ["S"]),
|
||||||
("unset", Just ["f", "v"]),
|
("unset", Just ["f", "v"]),
|
||||||
("wait", Just [])
|
("wait", Just [])
|
||||||
@@ -483,7 +488,7 @@ checkBashisms = ForShell [Sh, Dash, BusyboxSh] $ \t -> do
|
|||||||
"BASH_ARGV", "BASH_ARGV0", "BASH_CMDS", "BASH_COMMAND",
|
"BASH_ARGV", "BASH_ARGV0", "BASH_CMDS", "BASH_COMMAND",
|
||||||
"BASH_EXECUTION_STRING", "BASH_LINENO", "BASH_REMATCH", "BASH_SOURCE",
|
"BASH_EXECUTION_STRING", "BASH_LINENO", "BASH_REMATCH", "BASH_SOURCE",
|
||||||
"BASH_SUBSHELL", "BASH_VERSINFO", "EPOCHREALTIME", "EPOCHSECONDS",
|
"BASH_SUBSHELL", "BASH_VERSINFO", "EPOCHREALTIME", "EPOCHSECONDS",
|
||||||
"FUNCNAME", "GROUPS", "MACHTYPE", "MAPFILE"
|
"FUNCNAME", "GROUPS", "MAPFILE"
|
||||||
]
|
]
|
||||||
bashDynamicVars = [ "RANDOM", "SECONDS" ]
|
bashDynamicVars = [ "RANDOM", "SECONDS" ]
|
||||||
dashVars = [ "_" ]
|
dashVars = [ "_" ]
|
||||||
|
@@ -104,31 +104,31 @@ commonCommands = [
|
|||||||
"compress", "continue", "cp", "crontab", "csplit", "ctags", "cut",
|
"compress", "continue", "cp", "crontab", "csplit", "ctags", "cut",
|
||||||
"cxref", "date", "dd", "delta", "df", "diff", "dirname", "dot",
|
"cxref", "date", "dd", "delta", "df", "diff", "dirname", "dot",
|
||||||
"du", "echo", "ed", "env", "eval", "ex", "exec", "exit", "expand",
|
"du", "echo", "ed", "env", "eval", "ex", "exec", "exit", "expand",
|
||||||
"export", "expr", "fc", "fg", "file", "find", "fold", "fort77",
|
"export", "expr", "fc", "fg", "file", "find", "fold", "fuser",
|
||||||
"fuser", "gencat", "get", "getconf", "getopts", "grep", "hash",
|
"gencat", "get", "getconf", "getopts", "gettext", "grep", "hash",
|
||||||
"head", "iconv", "ipcrm", "ipcs", "jobs", "join", "kill", "lex",
|
"head", "iconv", "ipcrm", "ipcs", "jobs", "join", "kill", "lex",
|
||||||
"link", "ln", "locale", "localedef", "logger", "logname", "lp",
|
"link", "ln", "locale", "localedef", "logger", "logname", "lp",
|
||||||
"ls", "m4", "mailx", "make", "man", "mesg", "mkdir", "mkfifo",
|
"ls", "m4", "mailx", "make", "man", "mesg", "mkdir", "mkfifo",
|
||||||
"more", "mv", "newgrp", "nice", "nl", "nm", "nohup", "od", "paste",
|
"more", "msgfmt", "mv", "newgrp", "ngettext", "nice", "nl", "nm",
|
||||||
"patch", "pathchk", "pax", "pr", "printf", "prs", "ps", "pwd",
|
"nohup", "od", "paste", "patch", "pathchk", "pax", "pr", "printf",
|
||||||
"qalter", "qdel", "qhold", "qmove", "qmsg", "qrerun", "qrls",
|
"prs", "ps", "pwd", "read", "readlink", "readonly", "realpath",
|
||||||
"qselect", "qsig", "qstat", "qsub", "read", "readonly", "renice",
|
"renice", "return", "rm", "rmdel", "rmdir", "sact", "sccs", "sed",
|
||||||
"return", "rm", "rmdel", "rmdir", "sact", "sccs", "sed", "set",
|
"set", "sh", "shift", "sleep", "sort", "split", "strings", "strip",
|
||||||
"sh", "shift", "sleep", "sort", "split", "strings", "strip", "stty",
|
"stty", "tabs", "tail", "talk", "tee", "test", "time", "timeout",
|
||||||
"tabs", "tail", "talk", "tee", "test", "time", "times", "touch",
|
"times", "touch", "tput", "tr", "trap", "tsort", "tty", "type",
|
||||||
"tput", "tr", "trap", "tsort", "tty", "type", "ulimit", "umask",
|
"ulimit", "umask", "unalias", "uname", "uncompress", "unexpand",
|
||||||
"unalias", "uname", "uncompress", "unexpand", "unget", "uniq",
|
"unget", "uniq", "unlink", "unset", "uucp", "uudecode", "uuencode",
|
||||||
"unlink", "unset", "uucp", "uudecode", "uuencode", "uustat", "uux",
|
"uustat", "uux", "val", "vi", "wait", "wc", "what", "who", "write",
|
||||||
"val", "vi", "wait", "wc", "what", "who", "write", "xargs", "yacc",
|
"xargs", "xgettext", "yacc", "zcat"
|
||||||
"zcat"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
nonReadingCommands = [
|
nonReadingCommands = [
|
||||||
"alias", "basename", "bg", "cal", "cd", "chgrp", "chmod", "chown",
|
"alias", "basename", "bg", "cal", "cd", "chgrp", "chmod", "chown",
|
||||||
"cp", "du", "echo", "export", "fg", "fuser", "getconf",
|
"cp", "du", "echo", "export", "fg", "fuser", "getconf",
|
||||||
"getopt", "getopts", "ipcrm", "ipcs", "jobs", "kill", "ln", "ls",
|
"getopt", "getopts", "ipcrm", "ipcs", "jobs", "kill", "ln", "ls",
|
||||||
"locale", "mv", "printf", "ps", "pwd", "renice", "rm", "rmdir",
|
"locale", "mv", "printf", "ps", "pwd", "readlink", "realpath",
|
||||||
"set", "sleep", "touch", "trap", "ulimit", "unalias", "uname"
|
"renice", "rm", "rmdir", "set", "sleep", "touch", "trap", "ulimit",
|
||||||
|
"unalias", "uname"
|
||||||
]
|
]
|
||||||
|
|
||||||
sampleWords = [
|
sampleWords = [
|
||||||
|
Reference in New Issue
Block a user