1. Overview
Static analysis of code for detecting code smells and bugs is important for increasing code quality. There are several static analysis tools for different programming languages.
shellcheck is such a tool for analyzing shell scripts. However, sometimes, we may want to suppress some of the issues found by shellcheck.
In this tutorial, we’ll discuss how to prevent unwanted shellcheck messages.
We’ll use shellcheck version 0.9.0 in our examples.
2. Brief Information About shellcheck
shellcheck is a static analysis tool for shell scripts. It supports several shells, such as bash, sh, ksh, and dash.
shellcheck parses the scripts passed as arguments to it and reports its findings as issues. Each issue has a corresponding code, for example, SC1000. These issues are documented on separate pages in the ShellCheck Wiki. The issues have several severities like error, warning, info, and style.
shellcheck can display the results in different formats like JSON and XML. It can be integrated with several IDEs and tools for continuous inspection of code quality.
3. Example Shell Script
We’ll use the following script, hello.sh:
#!/bin/bash
name=$@
echo Hello $1
This script expects to get a name as an argument and greets the provided name. Let’s try it:
$ ./hello.sh Alice
Hello Alice
Although the script works as expected, let’s analyze it using shellcheck to check if it has any problems. It’s enough to pass the script as an argument to shellcheck:
$ shellcheck ./hello.sh
In ./hello.sh line 3:
name=$@
^--^ SC2034 (warning): name appears unused. Verify use (or export if used externally).
^-- SC2124 (warning): Assigning an array to a string! Assign as array, or use * instead of @ to concatenate.
In ./hello.sh line 4:
echo Hello $1
^-- SC2086 (info): Double quote to prevent globbing and word splitting.
Did you mean:
echo Hello "$1"
For more information:
https://www.shellcheck.net/wiki/SC2034 -- name appears unused. Verify use (...
https://www.shellcheck.net/wiki/SC2124 -- Assigning an array to a string! A...
https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing ...
The script seems to have several problems or issues in shellcheck jargon, according to the output of shellcheck.
Firstly, we assign the provided arguments to a variable name using the statement name=$@. But we don’t use the variable name later. shellcheck reports an issue about it, namely, SC2034 (warning): name appears unused. Verify use (or export if used externally). The code of this issue is SC2034.
Secondly, we try to assign an array, $@, to a variable, name. Therefore, we get the following message: ^– SC2124 (warning): Assigning an array to a string! Assign as array, or use * instead of @ to concatenate. The code of this issue is SC2124.
Finally, we use $1 in the statement echo Hello $1 without using double quotes around it. Generally, it’s a good practice to use variables within double quotes to prevent globbing. shellcheck gives an information message using the statement ^– SC2086 (info): Double quote to prevent globbing and word splitting. The code of this issue is SC2086.
In general, we should fix the issues found in the static analysis performed by shellcheck. However, there might be cases when we may prefer not to fix the issues, at least some of them. We’ll see how to suppress those types of issues in the next section.
4. Suppressing Messages
Let’s take a look at several methods for suppressing the messages reported by shellcheck.
4.1. Suppressing a Single Issue
We can suppress the messages corresponding to a specific issue using the -e option of shellcheck. For example, to suppress the messages corresponding to the issue SC2086, we pass -e SC2086 to shellcheck:
$ shellcheck -e SC2086 ./hello.sh
In ./hello.sh line 3:
name=$@
^--^ SC2034 (warning): name appears unused. Verify use (or export if used externally).
^-- SC2124 (warning): Assigning an array to a string! Assign as array, or use * instead of @ to concatenate.
For more information:
https://www.shellcheck.net/wiki/SC2034 -- name appears unused. Verify use (...
https://www.shellcheck.net/wiki/SC2124 -- Assigning an array to a string! A...
The information message corresponding to SC2086 doesn’t exist in the output now, as expected.
4.2. Suppressing Multiple Issues
It’s possible to suppress the messages corresponding to more than one type of issue. For example, we can suppress the messages corresponding to SC2086 and SC2124:
$ shellcheck -e SC2086,SC2124 ./hello.sh
In ./hello.sh line 3:
name=$@
^--^ SC2034 (warning): name appears unused. Verify use (or export if used externally).
For more information:
https://www.shellcheck.net/wiki/SC2034 -- name appears unused. Verify use (..
We just pass the codes of the issues using commas between the codes. It’s possible to use the –exclude option instead of -e because they’re the same. However, we must pass them to shellcheck as –exclude=SC2086,SC2124.
We may want shellcheck to consider only specific issues. We can use the -i option in this case. For example, we can suppress the messages of all issues other than SC2034 using -i SC2034:
$ shellcheck -i SC2034 ./hello.sh
In ./hello.sh line 3:
name=$@
^--^ SC2034 (warning): name appears unused. Verify use (or export if used externally).
For more information:
https://www.shellcheck.net/wiki/SC2034 -- name appears unused. Verify use (...
As is apparent from the output, we’re successful in suppressing messages other than SC2034.
We can use the –include option instead of -i because they’re the same. The usage of it is the same as –exclude.
4.3. Suppressing According to Severity
We can also suppress the messages according to the severity of the issues using the -S option. For example, we can suppress all messages with a severity lower than warning by passing warning to the -S option:
$ shellcheck -S warning ./hello.sh
In ./hello.sh line 3:
name=$@
^--^ SC2034 (warning): name appears unused. Verify use (or export if used externally).
^-- SC2124 (warning): Assigning an array to a string! Assign as array, or use * instead of @ to concatenate.
For more information:
https://www.shellcheck.net/wiki/SC2034 -- name appears unused. Verify use (...
https://www.shellcheck.net/wiki/SC2124 -- Assigning an array to a string! A...
The message with info severity, SC2086, doesn’t appear in the output now.
Let’s list messages only with error severity using -S error:
$ shellcheck -S error ./hello.sh
Now, there are no messages in the output of shellcheck, as expected.
4.4. Suppressing Using SHELLCHECK_OPTS
Another option is to use the SHELLCHECK_OPTS environment variable. We must assign the options we pass to shellcheck to SHELLCHECK_OPTS:
$ SHELLCHECK_OPTS="-e SC2086,SC2124"
$ shellcheck ./hello.sh
In ./hello.sh line 3:
name=$@
^--^ SC2034 (warning): name appears unused. Verify use (or export if used externally).
For more information:
https://www.shellcheck.net/wiki/SC2034 -- name appears unused. Verify use (...
We set the option -e SC2086,SC2124 to SHELLCHECK_OPTS using SHELLCHECK_OPTS=”-e SC2086,SC2124″. Then, we ran shellcheck without passing any options from the command line. As is apparent from the output, we’re successful in suppressing the messages about the issues with codes SC2086 and SC2124.
4.5. Using the disable Directive in the Script
We can also specify the issues whose messages we want to suppress in the shell script as a comment using the disable directive. For example, let’s suppress all messages by modifying hello.sh:
#!/bin/bash
#shellcheck disable=all
name=$@
echo Hello $1
We just added the second line, #shellcheck disable=all. The disable directive must be added after the shebang before any other command. There might be other comments before it.
Now, let’s analyze the script using shellcheck:
$ shellcheck ./hello.sh
There aren’t any messages in the output as expected.
We can specify specific issues by their codes separated with commas. For example, we can suppress the messages of SC2034 and SC2124 by adding the line #shellcheck disable=SC2034,SC2124.
This method of suppressing messages may not always be preferable as we need to modify the script.
4.6. Using .shellcheckrc
Another alternative for suppressing messages is to use the .shellcheckrc file. We can add the disable directives to this file. This file must be in our home directory or in the same directory as the scripts.
As an example, let’s use the following .shellcheckrc file in our local directory:
$ cat .shellcheckrc
disable=SC1000,SC1010
disable=SC2000-SC2200
The first directive, disable=SC1000,SC1010, specifies to suppress the messages of issues SC1000 and SC1010. Additionally, the second directive, disable=SC2000-SC2200, specifies to suppress all issues in the range SC2000 to SC2200.
Let’s analyze hello.sh now:
$ shellcheck ./hello.sh
There are no messages in the output now since the issues SC2034, SC2086, and SC2124 are in the range SC2000-SC2200.
We can use the directive disable=all in .shellcheckrc to suppress all messages.
Using .shellcheckrc might be preferable, as there is no need to modify the scripts.
5. Conclusion
In this article, we discussed how to prevent unwanted shellcheck messages.
Firstly, after learning about shellcheck, we saw that we could use its-e option to suppress the messages corresponding to a single or multiple issues. We also learned that we could suppress the messages of all issues other than the specified ones using the -i option.
Secondly, we learned how to suppress messages according to their severity using the -S option.
Then, we saw that it’s possible to pass options to shellcheck for suppressing messages using the SHELLCHECK_OPTS environment variable.
Finally, we learned that using the disable directive within shell scripts is another alternative. Additionally, we saw that we could use the disable directive in the .shellcheckrc file.