Showing 405 of 405 total issues
Double quote to prevent globbing and word splitting. Open
curl -X PUT http://localhost:8080/$TAIL -d @$TAIL
- Read upRead up
- Exclude checks
Double quote to prevent globbing and word splitting.
Problematic code:
echo $1
for i in $*; do :; done # this done and the next one also applies to expanding arrays.
for i in $@; do :; done
Correct code:
echo "$1"
for i in "$@"; do :; done # or, 'for i; do'
Rationale
The first code looks like "print the first argument". It's actually "Split the first argument by IFS (spaces, tabs and line feeds). Expand each of them as if it was a glob. Join all the resulting strings and filenames with spaces. Print the result."
The second one looks like "iterate through all arguments". It's actually "join all the arguments by the first character of IFS (space), split them by IFS and expand each of them as globs, and iterate on the resulting list". The third one skips the joining part.
Quoting variables prevents word splitting and glob expansion, and prevents the script from breaking when input contains spaces, line feeds, glob characters and such.
Strictly speaking, only expansions themselves need to be quoted, but for stylistic reasons, entire arguments with multiple variable and literal parts are often quoted as one:
$HOME/$dir/dist/bin/$file # Unquoted (bad)
"$HOME"/"$dir"/dist/bin/"$file" # Minimal quoting (good)
"$HOME/$dir/dist/bin/$file" # Canonical quoting (good)
When quoting composite arguments, make sure to exclude globs and brace expansions, which lose their special meaning in double quotes: "$HOME/$dir/src/*.c"
will not expand, but "$HOME/$dir/src"/*.c
will.
Note that $( )
starts a new context, and variables in it have to be quoted independently:
echo "This $variable is quoted $(but this $variable is not)"
echo "This $variable is quoted $(and now this "$variable" is too)"
Exceptions
Sometimes you want to split on spaces, like when building a command line:
options="-j 5 -B"
make $options file
Just quoting this doesn't work. Instead, you should have used an array (bash, ksh, zsh):
options=(-j 5 -B) # ksh: set -A options -- -j 5 -B
make "${options[@]}" file
or a function (POSIX):
make_with_flags() { make -j 5 -B "$@"; }
make_with_flags file
To split on spaces but not perform glob expansion, Posix has a set -f
to disable globbing. You can disable word splitting by setting IFS=''
.
Similarly, you might want an optional argument:
debug=""
[[ $1 == "--trace-commands" ]] && debug="-x"
bash $debug script
Quoting this doesn't work, since in the default case, "$debug"
would expand to one empty argument while $debug
would expand into zero arguments. In this case, you can use an array with zero or one elements as outlined above, or you can use an unquoted expansion with an alternate value:
debug=""
[[ $1 == "--trace-commands" ]] && debug="yes"
bash ${debug:+"-x"} script
This is better than an unquoted value because the alternative value can be properly quoted, e.g. wget ${output:+ -o "$output"}
.
As always, this warning can be [[ignore]]d on a case-by-case basis.
this is especially relevant when BASH many not be available for the array work around. For example, use in eval or in command options where script has total control of the variables...
FLAGS="-av -e 'ssh -x' --delete --delete-excluded"
...
# shellcheck disable=SC2086
eval rsync $FLAGS ~/dir remote_host:dir
Notice
Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
Headers should be surrounded by blank lines Open
#### Content views (child views)
- Read upRead up
- Exclude checks
MD022 - Headers should be surrounded by blank lines
Tags: headers, blank_lines
Aliases: blanks-around-headers
This rule is triggered when headers (any style) are either not preceded or not followed by a blank line:
# Header 1
Some text
Some more text
## Header 2
To fix this, ensure that all headers have a blank line both before and after (except where the header is at the beginning or end of the document):
# Header 1
Some text
Some more text
## Header 2
Rationale: Aside from aesthetic reasons, some parsers, including kramdown, will not parse headers that don't have a blank line before, and will parse them as regular text.
Use ./*glob* or -- *glob* so names with dashes won't become options. Open
mv *.scss ../../scss/module
- Read upRead up
- Exclude checks
Use ./*glob* or -- *glob* so names with dashes won't become options.
Problematic code:
rm *
Correct code:
rm ./*
or
rm -- *
Rationale
Since files and arguments are strings passed the same way, programs can't properly determine which is which, and rely on dashes to determine what's what.
A file named -f
(touch -- -f
) will not be deleted by the problematic code. It will instead be interpreted as a command line option, and rm
will even report success.
Using ./*
will instead cause the glob to be expanded into ./-f
, which no program will treat as an option.
Similarly, --
by convention indicates the end of options, and nothing after it will be treated like flags (except for some programs possibly still special casing -
as e.g. stdin).
Note that changing *
to ./*
in GNU Tar parameters will add ./
prefix to path names in the created archive. This may cause subtle problems (eg. to search for a specific file in archive, the ./
prefix must be specified as well). So using -- *
is a safer fix for GNU Tar commands.
For more information, see "Filenames and Pathnames in Shell: How to do it Correctly".
Notice
Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
Expressions don't expand in single quotes, use double quotes for that. Open
sed -i.bak -e 's/\$page/@page/g' print.scss
- Read upRead up
- Exclude checks
Expressions don't expand in single quotes, use double quotes for that.
Problematic code:
name=World
echo 'Hello $name'
Correct code:
name=World
echo "Hello $name"
Rationale:
Single quotes prevent expansion of everything, including variables and command substitution.
If you want to use the values of variables and such, use double quotes instead.
Note that if you have other items that needs single quoting, you can use both in a single word:
echo '$1 USD is '"$rate GBP"
Exceptions
If you want $stuff
to be a literal dollar sign followed by the characters "stuff", you can [[ignore]] this message.
ShellCheck tries to be smart about it, and won't warn when this is used with awk, perl and similar, but there are some inherent ambiguities like 'I have $1 in my wallet'
, which could be "one dollar" or "whatever's in the first parameter".
In the particular case of sed
, ShellCheck uses additional heuristics to try to separate cases like 's/$foo/bar/'
(failing to replace the variable $foo
) with from the false positives like '$d'
(delete last line). If you're still triggering these, consider being more generous with your spaces: use $ { s/foo/bar; }
instead of ${s/foo/bar/;}
Notice
Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
Use 'cd ... || exit' or 'cd ... || return' in case cd fails. Open
cd less
- Read upRead up
- Exclude checks
Use cd ... || exit in case cd fails.
Problematic code:
cd generated_files
rm -r *.c
func(){
cd foo
do_something
}
Correct code:
cd generated_files || exit
rm -r *.c
# For functions, you may want to use return:
func(){
cd foo || return
do_something
}
Rationale:
cd
can fail for a variety of reasons: misspelled paths, missing directories, missing permissions, broken symlinks and more.
If/when it does, the script will keep going and do all its operations in the wrong directory. This can be messy, especially if the operations involve creating or deleting a lot of files.
To avoid this, make sure you handle the cases when cd
fails. Ways to do this include
-
cd foo || exit
as suggested to just abort immediately -
if cd foo; then echo "Ok"; else echo "Fail"; fi
for custom handling -
<(cd foo && cmd)
as an alternative to<(cd foo || exit; cmd)
in<(..)
,$(..)
or( )
Exceptions:
ShellCheck does not give this warning when cd
is on the left of a ||
or &&
, or the condition of a if
, while
or until
loop. Having a set -e
command anywhere in the script will disable this message, even though it won't necessarily prevent the issue.
If you are accounting for cd
failures in a way shellcheck doesn't realize, you can disable this message with a [[directive]].
Notice
Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
Lists should be surrounded by blank lines Open
- [Models](http://backbonejs.org/#Model)
- Read upRead up
- Exclude checks
MD032 - Lists should be surrounded by blank lines
Tags: bullet, ul, ol, blank_lines
Aliases: blanks-around-lists
This rule is triggered when lists (of any kind) are either not preceded or not followed by a blank line:
Some text
* Some
* List
1. Some
2. List
Some text
To fix this, ensure that all lists have a blank line both before and after (except where the block is at the beginning or end of the document):
Some text
* Some
* List
1. Some
2. List
Some text
Rationale: Aside from aesthetic reasons, some parsers, including kramdown, will not parse lists that don't have blank lines before and after them.
Note: List items without hanging indents are a violation of this rule; list items with hanging indents are okay:
* This is
not okay
* This is
okay
Ambiguous variable name 'l' Open
relevant_locations = [l for l in relevant_locations if l in locations]
- Read upRead up
- Exclude checks
Never use the characters 'l', 'O', or 'I' as variable names.
In some fonts, these characters are indistinguishable from the
numerals one and zero. When tempted to use 'l', use 'L' instead.
Okay: L = 0
Okay: o = 123
Okay: i = 42
E741: l = 0
E741: O = 123
E741: I = 42
Variables can be bound in several other contexts, including class
and function definitions, 'global' and 'nonlocal' statements,
exception handlers, and 'with' and 'for' statements.
In addition, we have a special handling for function parameters.
Okay: except AttributeError as o:
Okay: with lock as L:
Okay: foo(l=12)
Okay: for a in foo(l=12):
E741: except AttributeError as O:
E741: with lock as l:
E741: global I
E741: nonlocal l
E741: def foo(l):
E741: def foo(l=12):
E741: l = foo(l=12)
E741: for l in range(10):
E742: class I(object):
E743: def l(x):
Lists should be surrounded by blank lines Open
- The model retrieves the relevant value from its key-value store by the id passed in and returns the value
- Read upRead up
- Exclude checks
MD032 - Lists should be surrounded by blank lines
Tags: bullet, ul, ol, blank_lines
Aliases: blanks-around-lists
This rule is triggered when lists (of any kind) are either not preceded or not followed by a blank line:
Some text
* Some
* List
1. Some
2. List
Some text
To fix this, ensure that all lists have a blank line both before and after (except where the block is at the beginning or end of the document):
Some text
* Some
* List
1. Some
2. List
Some text
Rationale: Aside from aesthetic reasons, some parsers, including kramdown, will not parse lists that don't have blank lines before and after them.
Note: List items without hanging indents are a violation of this rule; list items with hanging indents are okay:
* This is
not okay
* This is
okay
Do not assign a lambda expression, use a def Open
here = lambda *x: join(abspath(dirname(__file__)), *x)
- Read upRead up
- Exclude checks
Compound statements (on the same line) are generally discouraged.
While sometimes it's okay to put an if/for/while with a small body
on the same line, never do this for multi-clause statements.
Also avoid folding such long lines!
Always use a def statement instead of an assignment statement that
binds a lambda expression directly to a name.
Okay: if foo == 'blah':\n do_blah_thing()
Okay: do_one()
Okay: do_two()
Okay: do_three()
E701: if foo == 'blah': do_blah_thing()
E701: for x in lst: total += x
E701: while t < 10: t = delay()
E701: if foo == 'blah': do_blah_thing()
E701: else: do_non_blah_thing()
E701: try: something()
E701: finally: cleanup()
E701: if foo == 'blah': one(); two(); three()
E702: do_one(); do_two(); do_three()
E703: do_four(); # useless semicolon
E704: def f(x): return 2*x
E731: f = lambda x: 2*x
Ambiguous variable name 'l' Open
def not_markerless(l):
- Read upRead up
- Exclude checks
Never use the characters 'l', 'O', or 'I' as variable names.
In some fonts, these characters are indistinguishable from the
numerals one and zero. When tempted to use 'l', use 'L' instead.
Okay: L = 0
Okay: o = 123
Okay: i = 42
E741: l = 0
E741: O = 123
E741: I = 42
Variables can be bound in several other contexts, including class
and function definitions, 'global' and 'nonlocal' statements,
exception handlers, and 'with' and 'for' statements.
In addition, we have a special handling for function parameters.
Okay: except AttributeError as o:
Okay: with lock as L:
Okay: foo(l=12)
Okay: for a in foo(l=12):
E741: except AttributeError as O:
E741: with lock as l:
E741: global I
E741: nonlocal l
E741: def foo(l):
E741: def foo(l=12):
E741: l = foo(l=12)
E741: for l in range(10):
E742: class I(object):
E743: def l(x):
Double quote to prevent globbing and word splitting. Open
ls /usr/local/lib/node_modules | grep $1 >/dev/null 2>&1 || { local return_=0; }
- Read upRead up
- Exclude checks
Double quote to prevent globbing and word splitting.
Problematic code:
echo $1
for i in $*; do :; done # this done and the next one also applies to expanding arrays.
for i in $@; do :; done
Correct code:
echo "$1"
for i in "$@"; do :; done # or, 'for i; do'
Rationale
The first code looks like "print the first argument". It's actually "Split the first argument by IFS (spaces, tabs and line feeds). Expand each of them as if it was a glob. Join all the resulting strings and filenames with spaces. Print the result."
The second one looks like "iterate through all arguments". It's actually "join all the arguments by the first character of IFS (space), split them by IFS and expand each of them as globs, and iterate on the resulting list". The third one skips the joining part.
Quoting variables prevents word splitting and glob expansion, and prevents the script from breaking when input contains spaces, line feeds, glob characters and such.
Strictly speaking, only expansions themselves need to be quoted, but for stylistic reasons, entire arguments with multiple variable and literal parts are often quoted as one:
$HOME/$dir/dist/bin/$file # Unquoted (bad)
"$HOME"/"$dir"/dist/bin/"$file" # Minimal quoting (good)
"$HOME/$dir/dist/bin/$file" # Canonical quoting (good)
When quoting composite arguments, make sure to exclude globs and brace expansions, which lose their special meaning in double quotes: "$HOME/$dir/src/*.c"
will not expand, but "$HOME/$dir/src"/*.c
will.
Note that $( )
starts a new context, and variables in it have to be quoted independently:
echo "This $variable is quoted $(but this $variable is not)"
echo "This $variable is quoted $(and now this "$variable" is too)"
Exceptions
Sometimes you want to split on spaces, like when building a command line:
options="-j 5 -B"
make $options file
Just quoting this doesn't work. Instead, you should have used an array (bash, ksh, zsh):
options=(-j 5 -B) # ksh: set -A options -- -j 5 -B
make "${options[@]}" file
or a function (POSIX):
make_with_flags() { make -j 5 -B "$@"; }
make_with_flags file
To split on spaces but not perform glob expansion, Posix has a set -f
to disable globbing. You can disable word splitting by setting IFS=''
.
Similarly, you might want an optional argument:
debug=""
[[ $1 == "--trace-commands" ]] && debug="-x"
bash $debug script
Quoting this doesn't work, since in the default case, "$debug"
would expand to one empty argument while $debug
would expand into zero arguments. In this case, you can use an array with zero or one elements as outlined above, or you can use an unquoted expansion with an alternate value:
debug=""
[[ $1 == "--trace-commands" ]] && debug="yes"
bash ${debug:+"-x"} script
This is better than an unquoted value because the alternative value can be properly quoted, e.g. wget ${output:+ -o "$output"}
.
As always, this warning can be [[ignore]]d on a case-by-case basis.
this is especially relevant when BASH many not be available for the array work around. For example, use in eval or in command options where script has total control of the variables...
FLAGS="-av -e 'ssh -x' --delete --delete-excluded"
...
# shellcheck disable=SC2086
eval rsync $FLAGS ~/dir remote_host:dir
Notice
Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
Use ./*glob* or -- *glob* so names with dashes won't become options. Open
for TAIL in $(find */* -type f | sort -r)
- Read upRead up
- Exclude checks
Use ./*glob* or -- *glob* so names with dashes won't become options.
Problematic code:
rm *
Correct code:
rm ./*
or
rm -- *
Rationale
Since files and arguments are strings passed the same way, programs can't properly determine which is which, and rely on dashes to determine what's what.
A file named -f
(touch -- -f
) will not be deleted by the problematic code. It will instead be interpreted as a command line option, and rm
will even report success.
Using ./*
will instead cause the glob to be expanded into ./-f
, which no program will treat as an option.
Similarly, --
by convention indicates the end of options, and nothing after it will be treated like flags (except for some programs possibly still special casing -
as e.g. stdin).
Note that changing *
to ./*
in GNU Tar parameters will add ./
prefix to path names in the created archive. This may cause subtle problems (eg. to search for a specific file in archive, the ./
prefix must be specified as well). So using -- *
is a safer fix for GNU Tar commands.
For more information, see "Filenames and Pathnames in Shell: How to do it Correctly".
Notice
Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
Expressions don't expand in single quotes, use double quotes for that. Open
sed -i.bak -e 's/\$2x/@2x/g' module/interpretations.scss
- Read upRead up
- Exclude checks
Expressions don't expand in single quotes, use double quotes for that.
Problematic code:
name=World
echo 'Hello $name'
Correct code:
name=World
echo "Hello $name"
Rationale:
Single quotes prevent expansion of everything, including variables and command substitution.
If you want to use the values of variables and such, use double quotes instead.
Note that if you have other items that needs single quoting, you can use both in a single word:
echo '$1 USD is '"$rate GBP"
Exceptions
If you want $stuff
to be a literal dollar sign followed by the characters "stuff", you can [[ignore]] this message.
ShellCheck tries to be smart about it, and won't warn when this is used with awk, perl and similar, but there are some inherent ambiguities like 'I have $1 in my wallet'
, which could be "one dollar" or "whatever's in the first parameter".
In the particular case of sed
, ShellCheck uses additional heuristics to try to separate cases like 's/$foo/bar/'
(failing to replace the variable $foo
) with from the false positives like '$d'
(delete last line). If you're still triggering these, consider being more generous with your spaces: use $ { s/foo/bar; }
instead of ${s/foo/bar/;}
Notice
Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
Expressions don't expand in single quotes, use double quotes for that. Open
sed -i.bak -e 's/\$2x/@2x/g' module/sidebar.scss
- Read upRead up
- Exclude checks
Expressions don't expand in single quotes, use double quotes for that.
Problematic code:
name=World
echo 'Hello $name'
Correct code:
name=World
echo "Hello $name"
Rationale:
Single quotes prevent expansion of everything, including variables and command substitution.
If you want to use the values of variables and such, use double quotes instead.
Note that if you have other items that needs single quoting, you can use both in a single word:
echo '$1 USD is '"$rate GBP"
Exceptions
If you want $stuff
to be a literal dollar sign followed by the characters "stuff", you can [[ignore]] this message.
ShellCheck tries to be smart about it, and won't warn when this is used with awk, perl and similar, but there are some inherent ambiguities like 'I have $1 in my wallet'
, which could be "one dollar" or "whatever's in the first parameter".
In the particular case of sed
, ShellCheck uses additional heuristics to try to separate cases like 's/$foo/bar/'
(failing to replace the variable $foo
) with from the false positives like '$d'
(delete last line). If you're still triggering these, consider being more generous with your spaces: use $ { s/foo/bar; }
instead of ${s/foo/bar/;}
Notice
Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
Expressions don't expand in single quotes, use double quotes for that. Open
find . -type f -exec sed -i.bak 's/\$80_gray/\$gray_80/g' {} \;
- Read upRead up
- Exclude checks
Expressions don't expand in single quotes, use double quotes for that.
Problematic code:
name=World
echo 'Hello $name'
Correct code:
name=World
echo "Hello $name"
Rationale:
Single quotes prevent expansion of everything, including variables and command substitution.
If you want to use the values of variables and such, use double quotes instead.
Note that if you have other items that needs single quoting, you can use both in a single word:
echo '$1 USD is '"$rate GBP"
Exceptions
If you want $stuff
to be a literal dollar sign followed by the characters "stuff", you can [[ignore]] this message.
ShellCheck tries to be smart about it, and won't warn when this is used with awk, perl and similar, but there are some inherent ambiguities like 'I have $1 in my wallet'
, which could be "one dollar" or "whatever's in the first parameter".
In the particular case of sed
, ShellCheck uses additional heuristics to try to separate cases like 's/$foo/bar/'
(failing to replace the variable $foo
) with from the false positives like '$d'
(delete last line). If you're still triggering these, consider being more generous with your spaces: use $ { s/foo/bar; }
instead of ${s/foo/bar/;}
Notice
Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
Tips depend on target shell and yours is unknown. Add a shebang. Open
#########
- Read upRead up
- Exclude checks
Tips depend on target shell and yours is unknown. Add a shebang.
Problematic code:
echo "$RANDOM" # Does this work?
Correct code:
#!/bin/sh
echo "$RANDOM" # Unsupported in sh. Produces warning.
or
#!/bin/bash
echo "$RANDOM" # Supported in bash. No warnings.
Rationale:
Different shells support different features. To give effective advice, ShellCheck needs to know which shell your script is going to run on. You will get a different numbers of warnings about different things depending on your target shell.
ShellCheck normally determines your target shell from the shebang (having e.g. #!/bin/sh
as the first line). The shell can also be specified from the CLI with -s
, e.g. shellcheck -s sh file
.
If you don't specify shebang nor -s
, ShellCheck gives this message and proceeds with some default (bash
).
Note that this error can not be ignored with a [[directive]]. It is not a suggestion to improve your script, but a warning that ShellCheck lacks information it needs to be helpful.
Exceptions
None. Please either add a shebang or use -s
.
Notice
Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
Use ./*glob* or -- *glob* so names with dashes won't become options. Open
rm *.bak **/*.bak
- Read upRead up
- Exclude checks
Use ./*glob* or -- *glob* so names with dashes won't become options.
Problematic code:
rm *
Correct code:
rm ./*
or
rm -- *
Rationale
Since files and arguments are strings passed the same way, programs can't properly determine which is which, and rely on dashes to determine what's what.
A file named -f
(touch -- -f
) will not be deleted by the problematic code. It will instead be interpreted as a command line option, and rm
will even report success.
Using ./*
will instead cause the glob to be expanded into ./-f
, which no program will treat as an option.
Similarly, --
by convention indicates the end of options, and nothing after it will be treated like flags (except for some programs possibly still special casing -
as e.g. stdin).
Note that changing *
to ./*
in GNU Tar parameters will add ./
prefix to path names in the created archive. This may cause subtle problems (eg. to search for a specific file in archive, the ./
prefix must be specified as well). So using -- *
is a safer fix for GNU Tar commands.
For more information, see "Filenames and Pathnames in Shell: How to do it Correctly".
Notice
Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
Headers should be surrounded by blank lines Open
- [Sidebar](regulations/static/regulations/js/source/views/sidebar/sidebar-view.js)
- Read upRead up
- Exclude checks
MD022 - Headers should be surrounded by blank lines
Tags: headers, blank_lines
Aliases: blanks-around-headers
This rule is triggered when headers (any style) are either not preceded or not followed by a blank line:
# Header 1
Some text
Some more text
## Header 2
To fix this, ensure that all headers have a blank line both before and after (except where the header is at the beginning or end of the document):
# Header 1
Some text
Some more text
## Header 2
Rationale: Aside from aesthetic reasons, some parsers, including kramdown, will not parse headers that don't have a blank line before, and will parse them as regular text.
Headers should be surrounded by blank lines Open
## How should I add a new feature?
- Read upRead up
- Exclude checks
MD022 - Headers should be surrounded by blank lines
Tags: headers, blank_lines
Aliases: blanks-around-headers
This rule is triggered when headers (any style) are either not preceded or not followed by a blank line:
# Header 1
Some text
Some more text
## Header 2
To fix this, ensure that all headers have a blank line both before and after (except where the header is at the beginning or end of the document):
# Header 1
Some text
Some more text
## Header 2
Rationale: Aside from aesthetic reasons, some parsers, including kramdown, will not parse headers that don't have a blank line before, and will parse them as regular text.
Trailing punctuation in header Open
## How does eRegulations’ Backbone layer receive data?
- Read upRead up
- Exclude checks
MD026 - Trailing punctuation in header
Tags: headers
Aliases: no-trailing-punctuation
Parameters: punctuation (string; default ".,;:!?")
This rule is triggered on any header that has a punctuation character as the last character in the line:
# This is a header.
To fix this, remove any trailing punctuation:
# This is a header
Note: The punctuation parameter can be used to specify what characters class
as punctuation at the end of the header. For example, you can set it to
'.,;:!'
to allow headers with question marks in them, such as might be used
in an FAQ.