filib/codeclimate-shellcheck

View on GitHub
data/env.yml

Summary

Maintainability
Test Coverage
---
SC2141:
  remediation_points: 50000
  content:
    body: |
      ## Did you mean IFS=$'\t' ?

      ### Problematic code:

      ```sh
      IFS="\t"
      ```

      ### Correct code:

      ```sh
      IFS=$'\t'
      ```

      ### Rationale:

      `IFS="\t"` splits on backslash and the letter "t". `IFS=$'\t'` splits on tab.

      ### Exceptions

      It's extremely rare to want to split on the letter "n" or "t", rather than linefeed or tab.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2155:
  remediation_points: 50000
  content:
    body: |
      ## Declare and assign separately to avoid masking return values.

      ### Problematic code:

      ```sh
      export foo="$(mycmd)"
      ```

      ### Correct code:

      ```sh
      export foo
      foo=$(mycmd)
      ```

      ### Rationale:

      In the original code, the return value of `mycmd` is ignored, and `export` will instead always return true. This may prevent conditionals, `set -e` and traps from working correctly.

      When first marked for export and assigned separately, the return value of the assignment will be that of `mycmd`. This avoids the problem.

      ### Exceptions:

      If you intend to ignore the return value of an assignment, you can either ignore this warning or use

      ```sh
      export foo
      foo=$(mycmd) || true
      ```

      Shellcheck does not warn about `export foo=bar` because `bar` is a literal and not a command substitution with an independent return value. It also does not warn about `local -r foo=$(cmd)`, where declaration and assignment must be in the same command.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2003:
  remediation_points: 50000
  content:
    body: |
      # expr is antiquated. Consider rewriting this using $((..)), ${} or [[ ]].

      ### Problematic code:

      ```sh
      i=$(expr 1 + 2)
      l=$(expr length "$var")
      ```

      ### Correct code:

      ```sh
      i=$((1+2))
      l=${#var}
      ```

      ### Rationale:

      [To quote POSIX:](http://pubs.opengroup.org/onlinepubs/009695399/utilities/expr.html)

      > The expr utility has a rather difficult syntax [...] In many cases, the arithmetic and string features provided as part of the shell command language are easier to use than their equivalents in expr. Newly written scripts should avoid expr in favor of the new features within the shell.

      ### Exceptions

      `sh` doesn't have a great replacement for the `:` operator (regex match). ShellCheck tries not to warn when using expr with `:`, but e.g. `op=:; expr string "$op" regex` still trigger it.

      Other than that, all uses of `expr` can be rewritten to use modern shell features instead.

      Bash has `[[ string =~ regex ]]`, so not even `expr .. : ..` is necessary.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2122:
  remediation_points: 50000
  content:
    body: |
      ## >= is not a valid operator. Use '! a < b' instead.

      ### Problematic code:

      ```sh
      [[ a &lt;= b ]]
      ```

      ### Correct code:

      ```sh
      [[ ! a > b ]]
      ```

      ### Rationale:

      The operators `<=` and `>=` are not supported by Bourne shells. Instead of "less than or equal", rewrite as "not greater than".

      ### Exceptions

      None


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2063:
  remediation_points: 50000
  content:
    body: |
      # Grep uses regex, but this looks like a glob.

      ### Problematic code:

      ```sh
      grep '*foo*'
      ```

      ### Correct code:

      ```sh
      grep 'foo'   # or more explicitly,  grep '.*foo.*'
      ```

      ### Rationale:

      In globs, `*` matches any number of any character.

      In regex, `*` matches any number of the preceding character.

      `grep` uses regex, not globs, so this means that `grep '*foo'` is nonsensical because there's no preceding character for `*`.

      If the intention was to match "any number of characters followed by foo", use `'.*foo'`. Also note that since grep matches substrings, this will match "fishfood". Use anchors to prevent this, e.g. `foo$`.

      This also means that `f*` will match "hello", because `f*` matches 0 (or more) "f"s and there are indeed 0 "f" characters in "hello". Again, use `grep 'f'` to find strings containing "f", or `grep '^f'` to find strings starting with "f".


      ### Exceptions

      If you're aware of the differences between globs and regex, you can ignore this message.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2130:
  remediation_points: 50000
  content:
    body: |
      ## -eq is for integer comparisons. Use = instead.

      ### Problematic code:

      ```sh
      [[ $foo -eq "Y" ]]
      ```

      ### Correct code:

      ```sh
      [[ $foo = "Y" ]]
      ```

      ### Rationale:

      Shells have two sets of comparison operators: for integers (`-eq`, `-gt`, ...) and strings (`=`, `>`, ...). ShellCheck has noticed that you're using an integer comparison with string data.

      If you are in fact comparing integers, double check your parameters. Certain mistakes like `$$foo` or `${bar}}` can introduce non-numeric characters into otherwise numeric arguments.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2013:
  remediation_points: 50000
  content:
    body: |
      # To read lines rather than words, pipe/redirect to a 'while read' loop.

      ### Problematic code:

      ```sh
      for line in $(cat file | grep -v '^ *#')
      do
        echo "Line: $line"
      done
      ```

      ### Correct code:

      ```sh
      grep -v '^ *#' < file | while IFS= read -r line
      do
        echo "Line: $line"
      done
      ```

      or without a subshell (bash, zsh, ksh):

      ```sh
      while IFS= read -r line
      do
        echo "Line: $line"
      done < <(grep -v '^ *#' < file)
      ```

      ### Rationale:

      For loops by default (subject to `$IFS`) read word by word. Additionally, glob expansion will occur.

      Given this text file:

      ```sh
      foo *
      bar
      ```

      The for loop will print:

      ```sh
      Line: foo
      Line: aardwark.jpg
      Line: bullfrog.jpg
      ...
      ```

      The while loop will print:

      ```sh
      Line: foo *
      Line: bar
      ```


      ### Exceptions

      If you want to read word by word, you should still use a while read loop (e.g. with `read -a` to read words into an array).

      Rare reasons for ignoring this message is if you don't care because your file only contains numbers and you're not interested in good practices, or if you've set `$IFS` appropriately and also disabled globbing.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2115:
  remediation_points: 50000
  content:
    body: |
      ## Use "${var:?}" to ensure this never expands to /* .

      ### Problematic code:

      ```sh
      rm -rf "$STEAMROOT/"*
      ```

      ### Correct code:

      ```sh
      rm -rf "${STEAMROOT:?}/"*
      ```

      ### Rationale:

      If `STEAMROOT` is empty, this will [end up deleting everything](https://github.com/ValveSoftware/steam-for-linux/issues/3671) in the system's root directory.

      Using `:?` will cause the command to fail if the variable is null or unset. Similarly, you can use `:-` to set a default value if applicable.

      In the case command substitution, assign to a variable first and then use `:?`. This is relevant even if the command seems simple and obviously correct, since forks and execs can fail due to external system limits and conditions, resulting in a blank substitution.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2166:
  remediation_points: 50000
  content:
    body: |
      ## Prefer [ p ] && [ q ] as [ p -a q ] is not well defined.

      And likewise, prefer `[ p ] || [ q ]` over `[ p -o q ]`.

      ### Problematic code:

      ```sh
      [ "$1" = "test" -a -z "$2" ]
      ```

      ### Correct code:

      ```sh
      [ "$1" = "test" ] && [ -z "$2" ]
      ```

      ### Rationale:

      `-a` and `-o` to mean AND and OR in a `[ .. ]` test expression is not well defined. They are obsolescent extensions in [POSIX](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html) and their behavior is almost always undefined.

      Using multiple `[ .. ]` expressions with shell AND/OR operators `&&` and `||` is well defined and therefore preferred (but note that they have equal precedence, while `-a`/`-o` is unspecified but often implemented as `-a` having higher precedence).

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1038:
  remediation_points: 50000
  content:
    body: |
      ## Shells are space sensitive. Use '< <(cmd)', not '<<(cmd)'.

      ### Problematic code:

      ```sh
      while IFS= read -r line
      do
        printf "%q\n" "$line"
      done <<(curl -s http://example.com)
      ```

      ### Correct code:

      ```sh
      while IFS= read -r line
      do
        printf "%q\n" "$line"
      done <  <(curl -s http://example.com)
      ```

      ### Rationale:

      You are using `<<(` which is an invalid construct.

      You probably meant to redirect `<` from process substitution `<(..)` instead. To do this, a space is needed between the `<` and `<(..)`, i.e. `< <(cmd)`.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2173:
  remediation_points: 50000
  content:
    body: |
      ## SIGKILL/SIGSTOP can not be trapped.

      ### Problematic code:

      ```sh
      trap 'echo "unkillable"' KILL
      ```

      ### Correct code:

      Not applicable. This is not possible.

      ### Rationale:

      SIGKILL and SIGSTOP can not be caught/ignored (according to POSIX and as implemented on platforms including Linux and FreeBSD). Trying to trap this signal has undefined results.

      ### Exceptions:

      None. If you come across one, please file an issue about it.

      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2064:
  remediation_points: 50000
  content:
    body: |
      ## Use single quotes, otherwise this expands now rather than when signalled.

      ### Problematic code:

      ```sh
      trap "echo \"Finished on $(date)\"" EXIT
      ```

      ### Correct code:

      ```sh
      trap 'echo "Finished on $(date)"' EXIT
      ```

      ### Rationale:

      With double quotes, all parameter and command expansions will expand when the trap is defined rather than when it's executed.

      In the example, the message will contain the date on which the trap was declared, and not the date on which the script exits.

      Using single quotes will prevent expansion at declaration time, and save it for execution time.

      ### Exceptions

      If you don't care that the trap code is expanded early because the commands/variables won't change during execution of the script, or because you want to use the current and not the future values, then you can ignore this message.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2024:
  remediation_points: 50000
  content:
    body: "## sudo doesn't affect redirects. Use ..| sudo tee file\r\n\r\n### Problematic
      code:\r\n\r\nsudo echo 'export FOO=bar' >> /etc/profile\r\n\r\n### Correct code:\r\n\r\necho
      'export FOO=bar' | sudo tee -a /etc/profile > /dev/null\r\n\r\n### Rationale:\r\n\r\nRedirections
      are performed by the current shell before `sudo` is started. This means that
      it will use the current shell's user and permissions to open and write to the
      file.\r\n\r\n`tee` is a simple command that opens and writes to files without
      help from the shell, which means that it will use the permissions that `sudo`
      grants it.\r\n\r\nThere is nothing special about `tee`. It's just the simplest
      command that can both truncate and append to files without help from the shell.
      Here are equivalent alternatives:\r\n\r\nTruncating:\r\n\r\necho 'data' | sudo
      dd of=file\r\necho 'data' | sudo sed 'w file'\r\n\r\nAppending: \r\n\r\necho
      'data' | sudo awk '{ print $0 >> \"file\" }'\r\necho 'data' | sudo sh -c 'cat
      >> file'\r\n\r\n\r\n### Exceptions\r\n\r\nIf you want to run a command as root
      but redirect as the normal user, you can ignore this message.\n\n\n### Notice\n\nOriginal
      content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.\n"
SC2109:
  remediation_points: 50000
  content:
    body: |
      ## Instead of [ a || b ], use [ a ] || [ b ].

      ### Problematic code:

      ```sh
      [ "$1" = "-v" || "$1" = "-help" ]
      ```

      ### Correct code:

      ```sh
      [ "$1" = "-v" ] || [ "$1" = "-help" ]
      ```

      ### Rationale:

      `||` can not be used in a `[ .. ]` test expression. Instead, make two `[ .. ]` expressions and put the `||` between them.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2067:
  remediation_points: 50000
  content:
    body: |
      ## Missing ';' or + terminating -exec. You can't use |/||/&&, and ';' has to be a separate, quoted argument.

      ### Problematic code:

      ```sh
      find . -type f -exec shellcheck {} | wc -l \;
      find . -exec echo {} ;
      ```

      ### Correct code:

      ```sh
      find . -type f -exec sh -c 'shellcheck "$1" | wc -l' -- {} \;
      find . -exec echo {} \;
      ```

      ### Rationale:

      `find -exec` is still subject to all normal shell rules, so all shell features like `|`, `||`, `&` and `&&` will apply to the `find` command itself, and not to the command you are trying to construct with `-exec`.

      `find . -exec foo {} && bar {} \;` means run the command `find . -exec foo {}`, and if find is successful, run the command `bar "{}" ";"`.

      To instead go through each file and run `foo file && bar file` on it, invoke a shell that can interpret `&&`:

      ```sh
      find . -exec sh 'foo "$1" && bar "$1"' -- {} \;
      ```

      You can also use find `-a` instead of shell `&&`:

      ```sh
      find . -exec foo {} \; -a -exec bar {} \;
      ```

      This will have the same effect (`-a` is also the default when two commands are specified, and can therefore be omitted).

      ### Exceptions

      None


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2168:
  remediation_points: 50000
  content:
    body: |
      ## 'local' is only valid in functions.

      ### Problematic code:

      ```sh
      local foo=bar
      echo "$foo"
      ```

      ### Correct code:

      ```sh
      foo=bar
      echo "$foo"
      ```
      ### Rationale:

      In Bash, `local` can only be used in functions. In other contexts, it's an error.

      ### Exceptions:

      It's possible to source files containing `local` from a function context but not from any other context. This is not good practice, but in these cases you can [[ignore]] this error.

      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1098:
  remediation_points: 50000
  content:
    body: |
      ## Quote/escape special characters when using eval, e.g. eval "a=(b)".

      ### Problematic code:

      ```sh
      eval $var=(a b)
      ```

      ### Correct code:

      ```sh
      eval "$var=(a b)"
      ```

      ### Rationale:

      Shells differ widely in how they handle unescaped parentheses in `eval` expressions.

      * `eval foo=bar` is allowed by dash, bash and ksh.
      * `eval foo=(bar)` is allowed by bash and ksh, but not dash.
      * `eval $var=(bar)` is allowed by ksh, but not bash or dash.
      * `eval foo() ( echo bar; )` is not allowed by any shell.

      Since the expression is evaluated as shell script code anyways, it should be passed in as a literal string without relying on special case parsing rules in the target shell. Quote/escape the characters accordingly.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2020:
  remediation_points: 50000
  content:
    body: |
      # tr replaces sets of chars, not words (mentioned due to duplicates).

      ### Problematic code:

      ```sh
      echo 'hello world' | tr 'hello' 'goodbye'
      ```

      ### Correct code:

      ```sh
      echo 'hello world' | sed -e 's/hello/goodbye/g'
      ```

      ### Rationale:

      `tr` is for `tr`ansliteration, turning some characters into other characters. It doesn't match strings or words, only individual characters.

      In this case, it transliterates h->g, e->o, l->d, o->y, resulting in the string "goddb wbrdd" instead of "goodbye world".

      The solution is to use a tool that does string search and replace, such as sed.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1007:
  remediation_points: 50000
  content:
    body: |
      # Remove space after = if trying to assign a value (or for empty string, use var='' ... ).

      ### Problematic code:

      ```sh
      # I want programs to show text in dutch!
      LANGUAGE= nl
      ```

      ```sh
      # I want to run the nl command with English error messages!
      LANGUAGE= nl
      ```

      ### Correct code:

      ```sh
      # I want programs to show text in dutch!
      LANGUAGE=nl
      ```

      ```sh
      # I want to run the nl command with English error messages!
      LANGUAGE='' nl
      ```

      ### Rationale:

      It's easy to think that `LANGUAGE= nl` would assign `"nl"` to the variable `LANGUAGE`. It doesn't.

      Instead, it runs `nl` (the "number lines" command) and sets `LANGUAGE` to an empty string in its environment.

      Since trying to assign values this way is a common mistake, ShellCheck warns about it and asks you to be explicit when assigning empty strings (except for `IFS`, due to the common `IFS= read ..` idiom).

      ### Exceptions
      If you're familiar with this behavior and feel that the explicit version is unnecessary, you can [[ignore]] it.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2154:
  remediation_points: 50000
  content:
    body: |
      ## var is referenced but not assigned.

      ### Problematic code:

      ```sh
      var=name
      n=42
      echo "$var_$n.jpg"   # overextended
      ```

      or

      ```sh
      target="world"
      echo "hello $tagret"  # misspelled
      ```

      or

      ```sh
      echo "Result: ${mycmd -a myfile}"  # trying to execute commands
      ```

      ### Correct code:

      ```sh
      var=name
      n=42
      echo "${var}_$n.jpg"
      ```

      or

      ```sh
      target="world"
      echo "hello $target"
      ```

      or

      ```sh
      echo "Result: $(mycmd -a myfile)"
      ```

      ### Rationale:

      ShellCheck has noticed that you reference a variable that is not assigned. Double check that the variable is indeed assigned, and that the name is not misspelled.

      Note: This message only triggers for variables with lowercase characters in their name (`foo` and `kFOO` but not `FOO`) due to the standard convention of using lowercase variable names for unexported, local variables.

      ### Exceptions:

      ShellCheck does not attempt to figure out runtime or dynamic assignments like with `source "$(date +%F).sh"` or `eval var=value`.

      If you know for a fact that the variable is set, you can use `${var:?}` to fail if the variable is unset (or empty), or explicitly initialize/declare it with `var=""` or `declare var`. You can also disable the message with a [[directive]].


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1073:
  remediation_points: 50000
  content:
    body: |
      # Couldn't parse this ...

      This parsing error points to the structure ShellCheck was trying to parse when a parser error occurred. See [Parser error](Parser error) for more information.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2129:
  remediation_points: 50000
  content:
    body: |
      ## Consider using { cmd1; cmd2; } >> file instead of individual redirects.

      ### Problematic code:

      ```sh
      echo foo >> file
      date >> file
      cat stuff  >> file

      ```

      ### Correct code:

      ```sh
      {
        echo foo
        date
        cat stuff
      } >> file
      ```

      ### Rationale:

      Rather than adding `>> something` after every single line, you can simply group the relevant commands and redirect the group.

      ### Exceptions

      This is mainly a stylistic issue, and can freely be ignored.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1035:
  remediation_points: 50000
  content:
    body: |
      ## You need a space here

      ### Problematic code:

      ```sh
      if ![-z foo ]; then true; fi # if command `[-z' w/ args `foo', `]' fails..
      ```
      ### Correct code:

      ```sh
      if ! [ -z foo ]; then true; fi # if command `[' w/ args `-z', `foo', `]' fails..
      ```

      ### Rationale:

      Bourne shells are very whitespace sensitive. Adding or removing spaces can drastically alter the meaning of a script. In these cases, ShellCheck has noticed that you're missing a space at the position indicated.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2027:
  remediation_points: 50000
  content:
    body: |
      ## The surrounding quotes actually unquote this. Remove or escape them.

      ### Problematic code:

      ```sh
      echo "You enter "$HOSTNAME". You can smell the wumpus." >> /etc/issue
      ```

      ### Correct code:

      ```sh
      echo "You enter $HOSTNAME. You can smell the wumpus." >> /etc/issue
      ```

      ### Rationale:

      Always quoting variables and command expansions is good practice, but blindly putting quotes left and right of them is not.

      In this case, ShellCheck has noticed that the quotes around the expansion are unquoting it, because the left quote is terminating an existing double quoted string, while the right quote starts a new one:

      ```sh
      echo "You enter "$HOSTNAME". You can smell the wumpus."
           |----------|         |---------------------------|
              Quoted   No quotes           Quoted
      ```

      If the quotes were supposed to be literal, they should be escaped. If the quotes were supposed to quote an expansion (as in the example), they should be removed because this is already a double quoted string.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1079:
  remediation_points: 50000
  content:
    body: |
      ## This is actually an end quote, but due to next char it looks suspect.

      See companion warning [[SC1078]].


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2126:
  remediation_points: 50000
  content:
    body: |
      ## Consider using grep -c instead of grep|wc.

      ### Problematic code:

      ```sh
      grep foo | wc -l
      ```

      ### Correct code:

      ```sh
      grep -c foo
      ```

      ### Rationale:

      This is purely a stylistic issue. `grep` can count lines without piping to `wc`.

      Note that in many cases, this number is only used to see whether there are matches (i.e. `> 0`). In these cases, it's better and more efficient to use `grep -q` and check its exit status:

      ```sh
      if grep -q pattern file
      then
        echo "The file contains the pattern"
      fi
      ```

      ### Exceptions

      If you e.g. want to count characters instead of lines, and you actually care about the number and not just whether it's greater than 0.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1088:
  remediation_points: 50000
  content:
    body: |
      ## Parsing stopped here. Invalid use of parentheses?

      ### Problematic code:

      ```sh
      grep ^(.*)\1$ file
      ```

      or

      ```sh
      var = myfunction(value)
      ```

      ### Correct code:

      ```sh
      grep '^(.*)\1$' file
      ```

      or

      ```sh
      var=$(myfunction value)
      ```

      ### Rationale:

      Parentheses are shell syntax and must be used correctly.

      For commands that expect literal parentheses, such as `grep` or `find`, the parentheses need to be quoted or escaped so the shell does not interpret them, but instead passes them to the command.

      For shell syntax, the shell does not use them the way most other languages do, so avoid guessing at syntax based on previous experience. In particular:

      - Parentheses are NOT used to call functions.
      - Parentheses are NOT used to group expressions, except in arithmetic contexts.
      - Parentheses are NOT used in conditional statements or loops.
      - Parentheses are used differently in different contexts. `( .. )`, `$( .. )`, `$(( .. ))` and `var=(..)` are completely separate and independent structures with different meanings, and can not be broken down into operations on expressions in parentheses.

        In C-like languages, `++` can't be broken down into two `+` operations, so you can't e.g. use `+ +` or `+(+)`. In the same way, all of the above are completely unrelated so that you can't do `$(1+1)` or `$( (1+1) )` in place of `$(( 1+1 ))`.

      If you are trying to use parentheses for shell syntax, look up the actual syntax of the statement you are trying to use.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2068:
  remediation_points: 50000
  content:
    body: |
      ## Double quote array expansions to avoid re-splitting elements.

      ### Problematic code:

      ```sh
      cp $@ ~/dir
      ```

      ### Correct code:

      ```sh
      cp "$@" ~/dir
      ```

      ### Rationale:

      Double quotes around `$@` (and similarly, `${array[@]}`) prevents globbing and word splitting of individual elements, while still expanding to multiple separate arguments.

      Let's say you have three arguments: `baz`, `foo bar` and `*`

      `"$@"` will expand into exactly that: `baz`, `foo bar` and `*`

      `$@` will expand into multiple other arguments: `baz`, `foo`, `bar`, `file.txt` and `otherfile.jpg`

      Since the latter is rarely expected or desired, ShellCheck warns about it.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2088:
  remediation_points: 50000
  content:
    body: |
      ## Tilde does not expand in quotes. Use $HOME.

      ### Problematic code:

      ```sh
      rm "~/Desktop/$filename"
      ```

      ### Correct code:

      ```sh
      rm "$HOME/Desktop/$filename"
      ```

      ### Rationale:

      Tilde does not expand to the user's home directory when it's single or double quoted. Use double quotes and `$HOME` instead.

      Alternatively, the `~/` can be left unquoted, as in `rm ~/"Desktop/$filename"`.

      ### Exceptions

      If you don't want the tilde to be expanded, you can ignore this message.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2012:
  remediation_points: 50000
  content:
    body: |
      ## Use find instead of ls to better handle non-alphanumeric filenames.

      ### Problematic code:

      ```sh
      ls -l | grep " $USER " | grep '\.txt$'
      ```

      ### Correct code:

      ```sh
      find . -maxdepth 1 -name '*.txt' -user "$USER"
      ```

      ### Rationale:

      `ls` is only intended for human consumption: it has a loose, non-standard format and may "clean up" filenames to make output easier to read.

      Here's an example:

      ```sh
      $ ls -l
      total 0
      -rw-r----- 1 me me 0 Feb  5 20:11 foo?bar
      -rw-r----- 1 me me 0 Feb  5  2011 foo?bar
      -rw-r----- 1 me me 0 Feb  5 20:11 foo?bar
      ```

      It shows three seemingly identical filenames, and did you spot the time format change? How it formats and what it redacts can differ between locale settings, `ls` version, and whether output is a tty.

      `ls` can usually be substituted for `find` if it's the filenames you're after.

      If trying to parse out any other fields, first see whether `stat` (GNU, OS X, FreeBSD) or `find -printf` (GNU) can give you the data you want directly.

      ### Exceptions:

      If the information is intended for the user and not for processing (`ls -l ~/dir | nl; echo "Ok to delete these files?"`) you can ignore this error with a [[directive]].


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1068:
  remediation_points: 50000
  content:
    body: |
      # Don't put spaces around the = in assignments.

      ### Problematic code:

      ```sh
      foo = 42
      ```

      ### Correct code:

      ```sh
      foo=42
      ```

      ### Rationale:

      Shells are space sensitive. `foo=42` means to assign `42` to the variable `foo`. `foo = 42` means to run a command named `foo`, and pass `=` as `$1` and `42` as `$2`.

      ### Exceptions

      If you actually wanted to run a command named foo and provide `=` as the first argument, simply quote it to make ShellCheck be quiet: `foo "=" 42`.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2105:
  remediation_points: 50000
  content:
    body: |
      ## `break` is only valid in loops

      ### Problematic code:

      ```sh
      case "$1" in
          -v)
             verbose=1
             break
             ;;
          -d)
             debug=1
      esac
      ```

      ### Correct code:

      ```sh
      case "$1" in
          -v)
             verbose=1
             ;;
          -d)
             debug=1
      esac
      ```
      ### Rationale:

      `break` or `continue` was found outside a loop. These statements are only valid in loops. In particular, `break` is not required in `case` statements as there is no implicit fall-through.

      To return from a function or sourced script, use `return`. To exit a script, use `exit`.

      ### Exceptions:

      It's possible to `break`/`continue` in a function without a loop. The call will then affect the loop -- if any -- that the function is invoked from. This is obviously not good coding practice.

      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2029:
  remediation_points: 50000
  content:
    body: |
      ## Note that, unescaped, this expands on the client side.

      ### Problematic code:

      ```sh
      ssh host "echo $HOSTNAME"
      ```

      ### Correct code:

      ```sh
      ssh host "echo \$HOSTNAME"
      ```

      or

      ```sh
      ssh host 'echo $HOSTNAME'
      ```

      ### Rationale:

      Bash expands all arguments that are not escaped/singlequoted. This means that the problematic code is identical to

      ```sh
      ssh host "echo clienthostname"
      ```

      and will print out the client's hostname, not the server's hostname.

      By escaping the `$` in `$HOSTNAME`, it will be transmitted literally and evaluated on the server instead.

      ### Exceptions

      If you do want your string expanded on the client side, you can safely ignore this message.

      Keep in mind that the expanded string will be evaluated again on the server side, so for arbitrary variables and command output, you may need to add a layer of escaping with e.g. `printf %q`.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1000:
  remediation_points: 50000
  content:
    body: |
      # $ is not used specially and should therefore be escaped.

      ### Problematic code:

      ```sh
      echo "$"
      ```

      ### Correct code:

      ```sh
      echo "\$"
      ```

      ### Rationale:
      `$` is special in double quotes, but there are some cases where it's interpreted literally:

      1. Following a backslash: `echo "\$"`
      2. In a context where the shell can't make sense of it, such as at the end of the string, (`"foo$"`) or before some constructs (`"$'foo'"`).

      To avoid relying on strange and shell specific behavior, any `$` intended to be literal should be escaped with a backslash.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2094:
  remediation_points: 50000
  content:
    body: |
      # SC2094 Make sure not to read and write the same file in the same pipeline.

      ### Problematic code:

      ```sh
      grep foo file.txt | sed -e 's/foo/bar/g' > file.txt
      ```

      ### Correct code:

      ```sh
      grep foo file.txt  | sed -e 's/foo/bar/g' > tmpfile && mv tmpfile file.txt
      ```

      ### Rationale:

      Each step in a pipeline runs in parallel.

      In this case, `grep foo file.txt` will immediately try to read `file.txt` while `sed .. > file.txt` will immediately try to truncate it.

      This is a race condition, and results in the file being partially or (far more likely) entirely truncated.

      ### Exceptions

      You can ignore this error if:

      * The file is a device or named pipe. These files don't truncate in the same way.
      * The command mentions the filename but doesn't read/write it, such as `echo log.txt > log.txt`.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2046:
  remediation_points: 50000
  content:
    body: |
      # Quote this to prevent word splitting

      ### Problematic code:

          ls -l $(getfilename)

      ### Correct code:

          # getfilename outputs 1 file
          ls -l "$(getfilename)"

          # getfilename outputs multiple files, linefeed separated
          getfilename | while IFS='' read -r line
          do
            ls -l "$line"
          done

      ### Rationale:

      When command expansions are unquoted, word splitting and globbing will occur. This often manifests itself by breaking when filenames contain spaces.

      Trying to fix it by adding quotes or escapes to the data will not work. Instead, quote the command substitution itself.

      If the command substitution outputs multiple pieces of data, use a loop instead.

      ### Exceptions

      In rare cases you actually want word splitting, such as in

          gcc $(pkg-config --libs openssl) client.c

      This is because `pkg-config` outputs `-lssl -lcrypto`, which you want to break up by spaces into `-lssl` and `-lcrypto`.

      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1091:
  remediation_points: 50000
  content:
    body: |
      ## Not following: (error message here)

      Reasons include: file not found, no permissions, not included on the command line, not allowing `shellcheck` to follow files with `-x`, etc.

      ### Problematic code:

      ```sh
      source somefile
      ```

      ### Correct code:

      ```sh
      # shellcheck disable=SC1091
      source somefile
      ```

      ### Rationale:

      ShellCheck, for whichever reason, is not able to access the source file.

      This could be because you did not include it on the command line, did not use `shellcheck -x` to allow following other files, don't have permissions or a variety of other problems.

      Feel free to ignore the error with a [[directive]].

      ### Exceptions:

      If you're fine with it, ignore the message with a [[directive]].


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2139:
  remediation_points: 50000
  content:
    body: |
      ## This expands when defined, not when used. Consider escaping.

      ### Problematic code:

      ```sh
      alias whereami="echo $PWD"
      ```

      ### Correct code:

      ```sh
      alias whereami='echo $PWD'
      ```

      ### Rationale:

      With double quotes, this particular alias will be defined as `echo /home/me`, so it will always print the same path. This is rarely intended.

      By using single quotes or escaping any expansions, we define the alias as `echo $PWD`, which will be expanded when we use the alias. This is the far more common use case.

      ### Exceptions

      If you don't mind that your alias definition is expanded at define time, you can ignore this warning.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2069:
  remediation_points: 50000
  content:
    body: |
      ## The order of the 2>&1 and the redirect matters. The 2>&1 has to be last.

      ### Problematic code:

      ```sh
      firefox 2>&1 > /dev/null
      ```

      ### Correct code:

      ```sh
      firefox > /dev/null 2>&1
      ```

      ### Rationale:

      Redirections are handled in order.

      The problematic code means "Point stderr to where stdout is currently pointing (the terminal). Then point stdout to /dev/null".

      The correct code means "Point stdout to /dev/null. Then point stderr to where stdout is currently pointing (/dev/null)".

      In other words, the problematic code hides stdout and shows stderr. The correct code hides both stderr and stdout, which is usually the intention.

      ### Exceptions

      If you want stderr as stdout and stdout to a file, you can ignore this message.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2034:
  remediation_points: 50000
  content:
    body: |
      # foo appears unused. Verify it or export it.

      ### Problematic code:

      ```sh
      foo=42
      echo "$FOO"
      ```

      ### Correct code:

      ```sh
      foo=42
      echo "$foo"
      ```

      ### Rationale:

      Variables not used for anything are often associated with bugs, so ShellCheck warns about them.

      Also note that something like `local let foo=42` does not make a `let` statement local -- it instead declares an additional local variable named `let`.

      ### Exceptions

      ShellCheck may not always realize that the variable is in use (especially with indirection), and may not realize you don't care (with throwaway variables or unimplemented features).

      For throwaway variables, consider using `_` as a dummy:

      ```sh
      read _ last _ zip _ _ <<< "$str"
      echo "$last, $zip"
      ```

      or use a directive to disable the warning:

      ```sh
      # shellcheck disable=SC2034
      read first last email zip lat lng <<< "$str"
      echo "$last, $zip"
      ```

      For indirection, there's not much you can do without rewriting to use arrays or similar:

      ```sh
      bar=42  # will always appear unused
      foo=bar
      echo "${!foo}"
      ```

      This is expected behavior, and not a bug. There is no good way to statically analyze indirection in shell scripts, just like static C analyzers have a hard time preventing segfaults.

      As always, there are ways to [[ignore]] this and other messages if they frequently get in your way.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2163:
  remediation_points: 50000
  content:
    body: |
      ## Exporting an expansion rather than a variable.

      ### Problematic code:

      ```sh
      MYVAR=foo
      export $MYVAR
      ```

      ### Correct code:

      ```sh
      MYVAR=foo
      export MYVAR
      ```

      ### Rationale:

      `export` takes a variable name, but shellcheck has noticed that you give it an expanded variable instead. The problematic code does not export `MYVAR` but a variable called `foo` if any.

      ### Exceptions:

      If you do want to export the variable's value, e.g. due to indirection, you can disable this message with a directive:

      ```sh
      # shellcheck disable=SC2163
      export "$MYVAR"
      ```


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2160:
  remediation_points: 50000
  content:
    body: |
      ## Instead of '[ true ]', just use 'true'.

      ### Problematic code:

      ```sh
      if [ true ]
      then
        echo "always triggers"
      fi
      ```

      ### Correct code:

      ```sh
      if true
      then
        echo "always triggers"
      fi
      ```

      ### Rationale:

      This is a stylistic suggestion to use `true` instead of `[ true ]`.

      `[ true ]` seems to suggest that the value "true" is somehow relevant to the statement. This is not the case, it doesn't matter. You can replace it with `[ false ]` or `[ wombat ]`, and it will still always be true:

      String  | In brackets  | Outside brackets
      --------|--------------|-----------------
      true    | true         | true
      false   | true         | false
      wombat  | true         | unknown command

      It's therefore better to use it without brackets, so that the "true" actually matters.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2071:
  remediation_points: 50000
  content:
    body: "## > is for string comparisons. Use -gt instead.\n\n### Problematic code:\n\n```sh\nif
      [[ $var > 10 ]]\nthen\n  echo \"Incorrectly triggers when var=5\"\nfi\n```\n\n###
      Correct code:\n\n```sh\nif [[ $var -gt 10 ]]\nthen\n  echo \"Correct numerical
      comparison\"\nfi\n```\n### Rationale:\n\n`<` and `>`, in both `[[` and `[` (when
      escaped) will do a lexicographical comparison, not a numerical comparison. \n\nThis
      means that `[[ 5 > 10 ]]` is true because 5 comes after 10 alphabetically. Meanwhile
      `[[ 5 -gt 10 ]]` is false because 5 does not come after 10 numerically.\n\nIf
      you want to compare numbers by value, use the numerical comparison operators
      `-gt`, `-ge`, `-lt` and `-le`.\n\n### Exceptions:\n\nNone.\n\n### Notice\n\nOriginal
      content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.\n"
SC2022:
  remediation_points: 50000
  content:
    body: |
      # Note that unlike globs, o* here matches 'ooo' but not 'oscar'
      ### Problematic code:

      ```sh
      grep 'foo*'
      ```

      when wanting to match `food` and `foosball`, but not `mofo` or `keyfob`.

      ### Correct code:

      ```sh
      grep '^foo'
      ```

      ### Rationale:

      As a glob, `foo*` means "Any string starting with foo", e.g. `food` and `foosball`.

      As a regular expression, "foo*" means "f followed by 1 or more o's, anywhere", e.g. "mofo" or "keyfob".

      This construct is way more common as a glob than as a regex, so ShellCheck notifies you about it.

      ### Exceptions

      If you're aware of the above, you can ignore this message. If you'd like shellcheck to be quiet, use a [[directive]] or `'fo[o]*'`.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2059:
  remediation_points: 50000
  content:
    body: |
      # Don't use variables in the printf format string. Use printf "..%s.." "$foo".

      ### Problematic code:

      ```sh
      printf "Hello, $NAME\n"
      ```

      ### Correct code:

      ```sh
      printf "Hello, %s\n" "$NAME"
      ```

      ### Rationale:

      `printf` interprets escape sequences and format specifiers in the format string. If variables are included, any escape sequences or format specifiers in the data will be interpreted too, when you most likely wanted to treat it as data. Example:

      ```sh
      coverage='96%'
      printf "Unit test coverage: %s\n" "$coverage"
      printf "Unit test coverage: $coverage\n"
      ```

      The first printf writes `Unit test coverage: 96%`.

      The second writes ``bash: printf: `\': invalid format character``

      ### Exceptions

      Sometimes you may actually want to interpret data as a format string, like in:

      ```sh
      hexToAscii() { printf "\x$1"; }
      hexToAscii 21
      ```

      Like all warnings, you can selectively silence this warning with a [directive](Directive).


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2091:
  remediation_points: 50000
  content:
    body: |
      ## Remove surrounding $() to avoid executing output.

      ### Problematic code:

      ```sh
      if $(which epstopdf)
      then
        echo "Found epstopdf"
      fi
      ```

      ### Correct code:

      ```sh
      if which epstopdf
      then
        echo "Found epstopdf"
      fi
      ```

      ### Rationale:

      ShellCheck has detected that you have a command that just consists of a command substitution.

      This is typically done in order to try to get the shell to execute a command, because `$(..)` does indeed execute commands. However, it's also replaced by the output of that command.

      When you run `echo "The date is $(date +%F)"`, bash evalutes the `$(..)`. The command then becomes `echo "The date is 2015-04-29"`, which writes out the string `The date is 2015-04-29`

      The problem is when you use `$(date +%F)` alone as a command. Bash evaluates the `$(..)`, and the command then becomes `2015-04-29`. There is no command called `2015-04-29`, so you get `bash: 2015-04-29: command not found`.

      Sometimes this results in this confounding `command not found` messages. Other times you get even stranger issues, like the example problematic code which always evaluates to false.

      The solution is simply to remove the surrounding `$()`. This will execute the command instead of the command's output.

      ### Exceptions:

      If you really want to execute the output of a command rather than the command itself, you can ignore this message.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2004:
  remediation_points: 50000
  content:
    body: |
      # $/${} is unnecessary on arithmetic variables.

      ### Problematic code:

      ```sh
      echo $(($n+1))
      ```

      ### Correct code:

      ```sh
      echo $((n+1))
      ```

      ### Rationale:

      The `$` on regular variables in arithmetic contexts is unnecessary, and can even lead to subtle bugs. This is because the contents of `$((..))` is first expanded into a string, and then evaluated as an expression:

      ```sh
      $ a='1+1'
      $ echo $(($a * 5))    # becomes 1+1*5
      6
      $ echo $((a * 5))     # evaluates as (1+1)*5
      10
      ```

      The `$` is unavoidable for special variables like `$1` vs `1`, `$#` vs `#`. ShellCheck does not warn about these cases.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2123:
  remediation_points: 50000
  content:
    body: |
      ## PATH is the shell search path. Use another name.

      ### Problematic code:

      ```sh
      PATH=/my/dir
      cat "$PATH/myfile"
      ```

      ### Correct code:

      Good practice: always use lowercase for unexported variables.

      ```sh
      path=/my/dir
      cat "$path/myfile"
      ```

      Bad practice: use another uppercase name.

      ```sh
      MYPATH=/my/dir
      cat "$MYPATH/myfile"
      ```

      ### Rationale:

      `PATH` is where the shell looks for the commands it executes. By inadvertently overwriting it, the shell will be unable to find commands (like `cat` in this case).

      You get this warning when ShellCheck suspects that you didn't meant to overwrite it (because it's a single path with no path separators).

      Best shell scripting practice is to always use lowercase variable names to avoid accidentally overwriting exported and internal variables.

      ### Exceptions

      If you're aware of the above and really do want to set your shell search path to `/my/dir`, you can ignore this warning.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2076:
  remediation_points: 50000
  content:
    body: |
      ## Don't quote rhs of =~, it'll match literally rather than as a regex.

      ### Problematic code:

      ```sh
      [[ $foo =~ "^fo+bar$" ]]
      ```

      ### Correct code:

      ```sh
      [[ $foo =~ ^fo+bar$ ]]
      ```

      ### Rationale:

      Quotes on the right hand side of `=~` can be used to match literally, so that `[[ $1 =~ ^"$2".* ]]` works even if `$2` contains regex metacharacters. This mirrors the behavior of globs, `[[ $1 = "$2"* ]]`.

      This also means that the problematic code tries to match literal carets and plus signs instead of interpreting them as regular expression matchers.  To match as a regex, it must be unquoted.

      ### Exceptions:

      If you do want to match literally just to do a plain substring search, e.g. `[[ $foo =~ "bar" ]]`, you could ignore this message, but consider using a more canonical glob match instead: `[[ $foo = *"bar"* ]]`.

      ### Compatibility:

      * In Bash 3.2 and newer with shopt `compat31` *disabled (the default)*, quoted patterns are literal whereas unquoted patterns are parsed for regex metacharacters.
      * In Bash 3.2 and newer with shopt `compat31` *enabled*, quoted and unquoted patterns match identically.
      * In Bash 3.1 quoted and unquoted patterns match identically.

      See http://stackoverflow.com/questions/218156/bash-regex-with-quotes


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1065:
  remediation_points: 50000
  content:
    body: |
      ## Trying to declare parameters? Don't. Use () and refer to params as $1, $2..

      ### Problematic code:

      ```sh
      foo(input) {
        echo "$input"
      }
      foo("hello world");
      ```

      ### Correct code:

      ```sh
      foo() {
        echo "$1"
      }
      foo "hello world"
      ```

      ### Rationale:

      Shell script functions behave just like scripts and other commands:

        - They always take a 0 to N parameters, referred to with `$1`, `$2` etc. They can not declare parameters by name.
        - They are executed using `name arg1 arg2`, and not with parentheses as C-like languages.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2140:
  remediation_points: 50000
  content:
    body: |
      ##  Word is on the form "A"B"C" (B indicated). Did you mean "ABC" or "A\"B\"C"?

      ### Problematic code:

      ```sh
      echo "<img src="foo.png" />" > file.html
      ```

      or

      ```sh
      export "var"="42"
      ```

      ### Correct code:

      ```sh
      echo "<img src=\"foo.png\" />" > file.html
      ```

      or

      ```sh
      export "var=42"
      ```


      ### Rationale:

      This warning triggers when an unquoted literal string is found suspiciously sandwiched between two double quoted strings.

      This usually indicates one of:

      - quotes that were supposed to be nested, and therefore need to be escaped (like the `<img>` example)
      - quotes that are just plain unnecessary (like the `export` example).

      Without escaping, the inner two quotes of the sandwich (the end quote of the first section and the start quote of the second section) are no-ops. The following two statements are identical, so the quotes that were intended to be part of the html output are instead removed:

      ```sh
      echo "<img src="foo.png" />" > file.html
      echo "<img src=foo.png />" > file.html
      ```

      Similarly, these statements are identical, but work as intended:

      ```sh
      export "var"="42"
      export "var=42"
      ```

      ### Exceptions

      If you know that the quotes are ineffectual but you prefer it stylistically, you can ignore this message.

      It's common not to realize that double quotes can span multiple elements, or to stylistically prefer to quote individual variables. For example, these statements are identical, but the first is laboriously and redundantly quoted:

      ```sh
      http://"$user":"$password"@"$host"/"$path"
      "http://$user:$password@$host/$path"
      ```

      When ShellCheck detects the first style (i.e. the double quotes include only a single element each), it will suppress the warning.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2158:
  remediation_points: 50000
  content:
    body: |
      ## [ false ] is true. Remove the brackets

      ### Problematic code:

      ```sh
      if [ false ]
      then
        echo "triggers anyways"
      fi
      ```

      ### Correct code:

      ```sh
      if false
      then
        echo "never triggers"
      fi
      ```

      ### Rationale:

      `[ str ]` checks whether `str` is non-empty. It doesn't matter if `str` is `false`, it will still be evaluated for non-emptyness.

      Instead, use the command `false` which -- as the manual puts it -- does nothing, unsuccessfully.

      ### Exceptions:

      None


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2006:
  remediation_points: 50000
  content:
    body: |
      # Use $(..) instead of legacy \`..\`

      ### Problematic code

      ```sh
      echo "Current time: `date`"
      ```

      ### Correct code

      ```sh
      echo "Current time: $(date)"
      ```

      ### Rationale

      Backtick command substitution `` `..` `` is legacy syntax with several issues.

      1. It has a series of undefined behaviors related to quoting in POSIX.
      1. It imposes a custom escaping mode with surprising results.
      1. It's exceptionally hard to nest.

      `$(..)` command substitution has none of these problems, and is therefore strongly encouraged.

      ### Exceptions

      None.

      ### See also

      - http://mywiki.wooledge.org/BashFAQ/082


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2096:
  remediation_points: 50000
  content:
    body: |
      ## On most OS, shebangs can only specify a single parameter.

      ### Problematic code:

      ```sh
      #!/usr/bin/env bash -x
      ```

      ### Correct code:

      ```sh
      #!/usr/bin/env bash
      set -x
      ```

      ### Rationale:

      Most operating systems, including Linux, FreeBSD and OS X, allow only a single parameter in the shebang. The example is equivalent to calling `env 'bash -x'` instead of `env 'bash' '-x'`, and it will therefore fail.

      The shebang should be rewritten to use at most one parameter. Shell options can instead be set in the body of the script.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1009:
  remediation_points: 50000
  content:
    body: |
      #  The mentioned parser error was in ...

      This info warning points to the start of what ShellCheck was parsing when it failed. See [Parser Error](Parser Error) for example and information.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2116:
  remediation_points: 50000
  content:
    body: |
      ## SC2116 Useless echo? Instead of 'cmd $(echo foo)', just use 'cmd foo'.

      ### Problematic code:

      ```sh
      a=$(echo $?)
      ```

      ### Correct code:

      ```sh
      a="$?"
      ```

      ### Rationale:

      Most of the time, this is an useless echo meaning it isn't doing anything that the Shell can't already do. Having the shell expand the contents for you is simpler and more reliable. Just remember to double quote the argument!

      ### Exceptions

      None I am aware of at the moment.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1097:
  remediation_points: 50000
  content:
    body: |
      ## Unexpected ==. For assignment, use =. For comparison, use [/[[.

      ### Problematic code:

      ```sh
      var==value
      ```

      ### Correct code:

      Assignment:

      ```sh
      var=value
      ```

      Comparison:

      ```sh
      [ "$var" = value ]
      ```

      ### Rationale:

      ShellCheck has noticed that you're using `==` in an unexpected way. The two most common reasons for this is:

      * You wanted to assign a value but accidentally used `==` instead of `=`.

      * You wanted to compare two values, but neglected to use `[ .. ]` or `[[ .. ]]`.

      ### Exceptions:

      If you wanted to assign a literal equals sign, use quotes to make this clear:

      ```sh
      var="=sum(A1:A10)"
      ```


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1084:
  remediation_points: 50000
  content:
    body: |
      ## Use #!, not !#, for the shebang.

      ### Problematic code:

      ```sh
      !#/bin/sh
      echo "Hello World"
      ```

      ### Correct code:

      ```sh
      #!/bin/sh
      echo "Hello World"
      ```

      ### Rationale:

      The shebang has been accidentally swapped. The `#` should come first: `#!`, not `!#`.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2119:
  remediation_points: 50000
  content:
    body: |
      # Use foo "$@" if function's $1 should mean script's $1.

      See companion warning [[SC2120]].


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2048:
  remediation_points: 50000
  content:
    body: |
      ## Use "$@" (with quotes) to prevent whitespace problems.

      ### Problematic code:

      ```sh
      cp $* ~/dir
      ```

      ### Correct code:

      ```sh
      cp "$@" ~/dir
      ```

      ### Rationale:

      `$*`, unquoted, is subject to word splitting and globbing.

      Let's say you have three arguments: `baz`, `foo bar` and `*`

      `"$@"` will expand into exactly that: `baz`, `foo bar` and `*`

      `$*` will expand into multiple other arguments: `baz`, `foo`, `bar`, `file.txt` and `otherfile.jpg`

      Since the latter is rarely expected or desired, ShellCheck warns about it.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2031:
  remediation_points: 50000
  content:
    body: |
      # var was modified in a subshell. That change might be lost.

      ### Problematic code:

      There are many ways of accidentally creating subshells, but a common one is piping to a loop:

      ```bash
      n=0
      printf "%s\n" {1..10} | while read i; do (( n+=i )); done
      echo $n
      ```

      ### Correct code:

      ```bash
      # Bash specific: process substitution. Also try shopts like lastpipe.
      n=0
      while read i; do (( n+=i )); done < <(printf "%s\n" {1..10})
      echo $n
      ```

      In `sh`, a temp file (better if fifo or fd) can be used instead of process substitution. And if it's acceptable to do it with waiting, try Here Documents.

      ### Rationale:

      Variables set in subshells are not available outside the subshell. This is a wide topic, and better described on the [Wooledge Bash Wiki](http://mywiki.wooledge.org/BashFAQ/024).

      Here are some constructs that cause subshells (shellcheck may not warn about all of them). In each case, you can replace `subshell1` by a command or function that sets a variable, e.g. simply `var=foo`, and the variable will appear to be unset after the command is run. Similarly, you can replace `regular` with `var=foo`, and it will be set afterwards:

      Pipelines:

      ```sh
      subshell1 | subshell2 | subshell3    # Bash, Dash, Ash
      subshell1 | subshell2 | regular      # Ksh, Zsh
      ```

      Command substitution:

      ```sh
      regular "$(subshell1)" "`subshell2`"
      ```

      Process substitution:

      ```sh
      regular <(subshell1) >(subshell2)
      ```

      Some forms of grouping:

      ```sh
      ( subshell )
      { regular; }
      ```

      Backgrounding:

      ```sh
      subshell1 &
      subshell2 &
      ```

      Anything executed by external processes:

      ```sh
      find . -exec subshell1 {} \;
      find . -print0 | xargs -0 subshell2
      sudo subshell3
      su -c subshell4
      ```

      This applies not only to setting variables, but also setting shell options and changing directories.

      ### Exceptions

      You can ignore this error if you don't care that the changes aren't reflected, because work on the value branches and shouldn't be recombined.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2146:
  remediation_points: 50000
  content:
    body: |
      ## This action ignores everything before the -o. Use \\( \\) to group.

      ### Problematic code:

      ```sh
      find . -name '*.avi' -o -name '*.mkv' -exec cp {} /media \;
      ```

      ### Correct code:

      ```sh
      find . \( -name '*.avi' -o -name '*.mkv' \) -exec cp {} /media \;
      ```

      ### Rationale:

      In `find`, two predicates with no operator between them is considered a logical, short-circuiting AND (as if using `-a`). E.g., `-name '*.mkv' -exec ..` is the same as `-name '*.mkv' -a -exec ..`.

      `-a` has higher precedence than `-o`, so `-name '*.avi' -o -name '*.mkv' -a -exec ..` is equivalent to `-name '*.avi' -o \( -name '*.mkv' -a -exec .. \)`.

      In other words, the problematic code means "if name matches `*.avi`, do nothing. Otherwise, if it matches `*.mkv`, execute a command.".

      In the correct code, we use `\( \)` to group to get the evaluation order we want. The correct code means "if name matches `*.avi` or `*.mkv`, then execute a command", which was what was intended.

      ### Exceptions

      If you're aware of this, you can either ignore this error or group to make it explicit. For example, to decompress all gz files except tar.gz, you can use:

      ```sh
      find . -name '*.tar.gz' -o \( -name '*.gz' -exec gzip -d {} + \)
      ```


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2065:
  remediation_points: 50000
  content:
    body: |
      ## This is interpreted as a shell file redirection, not a comparison.

      ### Problematic code:

      ```sh
      [ 1 >2 ] || [ 3>'aaa bb' ] # Simple example of problematic code
      ```

      ### Correct code:

      ```sh
      [ 1 -gt 2 ] || [ 3 \> 'aaa bb' ] # arithmetical, lexicographical
      ```
      ### Rationale:

      A word that looks like a redirection in simple shell commands causes it to be interpreted as a redirection.
      ShellCheck would guess that you don't want it in tests.

      ### Exceptions:

      When it's among a continuous list of redirections at the end of a simple `test` command, it's more likely that
      the user really meant to do a redirection. Or any other case that you mean to do that.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2147:
  remediation_points: 50000
  content:
    body: |
      ##  Literal tilde in PATH works poorly across programs.

      ### Problematic code:

      ```sh
      PATH="$PATH:~/bin"
      ```

      ### Correct code:

      ```sh
      PATH="$PATH:$HOME/bin"
      ```

      ### Rationale:

      Having literal `~` in PATH is a bad idea. Bash handles it, but nothing else does.

      This means that even if you're always using Bash, you should avoid it because any invoked program that relies on PATH will effectively ignore those entries.

      For example, `make` may say `foo: Command not found` even though `foo` works fine from the shell and Make and Bash both use the same PATH. You'll get similar messages from any non-bash scripts invoked, and `whereis` will come up empty.

      Use `$HOME` or full path instead.

      ### Exceptions

      If your directory name actually contains a literal tilde, you can ignore this message.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1010:
  remediation_points: 50000
  content:
    body: "## Use semicolon or linefeed before 'done' (or quote to make it literal).\r\n\r\n###
      Problematic code:\r\n\r\nfor f in *; do echo \"$f\" done\r\n\r\n### Correct
      code:\r\n\r\nfor f in *; do echo \"$f\"; done\r\n\r\n### Rationale:\r\n\r\n`done`
      only works as a keyword when it's the first token of the command. If added after
      a command, it will just be the literal word \"done\". \r\n\r\n### Exceptions\r\n\r\nIf
      you're intentionally using `done` as a literal, you can quote it to make this
      clear to shellcheck (and also human readers), e.g. instead of `echo Task is
      done`, use `echo \"Task is done\"`. This makes no difference to the shell, but
      it will silence this warning.\n\n\n### Notice\n\nOriginal content from the ShellCheck
      https://github.com/koalaman/shellcheck/wiki.\n"
SC2015:
  remediation_points: 50000
  content:
    body: |
      # Note that A && B || C is not if-then-else. C may run when A is true.

      ### Problematic code:

      ```sh
      [[ $dryrun ]] && echo "Would delete file" || rm file
      ```

      ### Correct code:

      ```sh
      if [[ $dryrun ]]
      then
        echo "Would delete file"
      else
        rm file
      fi
      ```

      ### Rationale:

      It's common to use `A && B` to run `B` when `A` is true, and `A || C` to run `C` when `A` is false.

      However, combining them into `A && B || C` is not the same as `if A then B else C`.

      In this case, if `A` is true but `B` is false, `C` will run.

      For the code sample above, if the script was run with stdout closed for any reason (such as explicitly running `script --dryrun >&-`), echo would fail and the file would be deleted, even though `$dryrun` was set!

      If an `if` clause is used instead, this problem is avoided.

      ### Exceptions
      Ignore this warning when you actually do intend to run C when either A or B fails.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2162:
  remediation_points: 50000
  content:
    body: |
      ## read without -r mangles backslashes

      ### Problematic code:

      ```sh
      echo "Enter name:"
      read name
      ```

      ### Correct code:

      ```sh
      echo "Enter name:"
      read -r name
      ```

      ### Rationale:

      By default, `read` will interpret backslashes before spaces and line feeds, and otherwise strip them. This is rarely expected or desired.

      Normally you just want to read data, which is what `read -r` does. All `read`s should use `-r` unless you have a good reason not to.

      Note that `read -r` will still strip leading and trailing spaces. `IFS="" read -r` prevents this.

      ### Exceptions:

      If you want backslashes to affect field splitting and line terminators instead of being read, you can disable this message with a [[directive]].


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2070:
  remediation_points: 50000
  content:
    body: |
      ## -n doesn't work with unquoted arguments. Quote or use [\[ ]].

      ### Problematic code:

      ```sh
      if [ -n $var ]
      then
        echo "var has a value"
      else
        echo "var is empty"
      fi
      ```

      ### Correct code:

      In POSIX:

      ```sh
      if [ -n "$var" ]
      then
        echo "var has a value"
      else
        echo "var is empty"
      fi
      ```

      In bash/ksh:

      ```sh
      if [[ -n $var ]]
      then
        echo "var has a value"
      else
        echo "var is empty"
      fi
      ```


      ### Rationale:

      When `$var` is unquoted, a blank value will cause it to wordsplit and disappear. If `$var` is empty, these two statements are identical:

      ```sh
      [ -n $var ]
      [ -n ]
      ```

      `[ string ]` is shorthand for testing if a string is empty. This is still true if `string` happens to be `-n`. `[ -n ]` is therefore true, and by extension so is `[ -n $var ]`.

      To fix this, either quote the variable, or (if your shell supports it) use `[[ -n $var ]]` which generally has fewer caveats than `[`.

      ### Exceptions:

      None


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2089:
  remediation_points: 50000
  content:
    body: |
      # Quotes/backslashes will be treated literally. Use an array.

      ### Problematic code:

      ```sh
      args='-lh "My File.txt"'
      ls $args
      ```

      ### Correct code:

      ```sh
      args=(-lh "My File.txt")
      ls "${args[@]}"
      ```

      ### Rationale:

      Bash does not interpret data as code. Consider almost any other languages, such as Python:

      ```sh
      print 1+1   # prints 2
      a="1+1"
      print a     # prints 1+1, not 2
      ```

      Here, `1+1` is Python syntax for adding numbers. However, passing a literal string containing this expression does not cause Python to interpret it, see the `+` and produce the calculated result.

      Similarly, `"My File.txt"` is Bash syntax for a single word with a space in it. However, passing a literal string containing this expression does not cause Bash to interpret it, see the quotes and produce the tokenized result.

      The solution is to use an array instead, whenever possible.

      If you due to `sh` compatibility can't use arrays, you can use `eval` instead. However, this is very insecure and easy to get wrong, leading to various forms of security vulnerabilities and breakage:

      ```sh
      quote() { local q=${1//\'/\'\\\'\'}; echo "'$q'"; }
      args="-lh $(quote "My File.txt")"
      eval ls "$args" # Do not use unless you understand implications
      ```

      If you ever accidentally forget to use proper quotes, such as with:

      ```sh
      for f in *.txt; do
        args="-lh '$1'" # Example security exploit
        eval ls "$args" # Do not copy and use
      done
      ```

      Then you can use `touch "'; rm -rf \$'\x2F'; '.txt"`  (or someone can trick you into downloading a file with this name, or create a zip file or git repo containing it, or changing their nick and have your chat client create the file for a chat log, or...), and running the script to list your files will run the command `rm -rf /`.

      ### Exceptions

      Few and far between.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1066:
  remediation_points: 50000
  content:
    body: |
      ## Don't use $ on the left side of assignments.

      ### Problematic code:

      ```sh
      $greeting="Hello World"
      ```

      ### Correct code:

      ```sh
      greeting="Hello World"
      ```

      Alternatively, if the goal was to assign to a variable whose name is in another variable (indirection), use `declare`:

      ```sh
      name=foo
      declare "$name=hello world"
      echo "$foo"
      ```

      ### Rationale:

      Unlike Perl or PHP, `$` is not used when assigning to a variable.

      ### Exceptions

      None


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2032:
  remediation_points: 50000
  content:
    body: |
      # Use own script or sh -c '..' to run this from su.

      See [[SC2033]].


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2061:
  remediation_points: 50000
  content:
    body: "## Quote the parameter to -name so the shell won't interpret it.\n\n###
      Problematic code:\n\n```sh\nfind . -name *.txt\n```\n\n### Correct code:\n\n```sh\nfind
      . -name '*.txt'\n```\n### Rationale:\n\nSeveral find options take patterns to
      match against, including `-ilname`, `-iname`, `-ipath`, `-iregex`, `-iwholename`,
      `-lname`, `-name`, `-path`, `-regex` and `-wholename`.\n\nThese compete with
      the shell's pattern expansion, and must therefore be quoted so that they are
      passed literally to `find`.\n\nThe example command may end up executing as `find
      . -name README.txt` after the shell has replaced the `*.txt` with a matching
      file `README.txt` from the current directory. \n\nThis may happen today or suddenly
      in the future.\n\n### Exceptions:\n\nNone.\n\n### Notice\n\nOriginal content
      from the ShellCheck https://github.com/koalaman/shellcheck/wiki.\n"
SC2157:
  remediation_points: 50000
  content:
    body: |
      ## Argument to implicit -n is always true due to literal strings.

      ### Problematic code:

      ```sh
      if [ "$foo " ]
      then
        echo "this is always true"
      fi
      ```

      ### Correct code:

      ```sh
      if [ "$foo" ]
      then
        echo "correctly checks value"
      fi
      ```

      ### Rationale:

      Since `[ str ]` checks that the string is non-empty, the space inside the quotes in the problematic code causes the test to always be true, since a string with a space can not be empty.

      Sometimes this is also caused by overquoting an example, e.g. `[ "$foo -gt 0" ]`, which is always true for the same reason. The intention here was `[ "$foo" -gt 0 ]`.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2026:
  remediation_points: 50000
  content:
    body: |
      ## This word is outside of quotes. Did you intend to `'nest '"'single quotes'"'` instead'?

      ### Problematic code:

      ```sh
      alias server_uptime='ssh $host 'uptime -p''
      ```

      ### Correct code:

      ```sh
      alias server_uptime='ssh $host '"'uptime -p'"
      ```

      ### Rationale:

      In the first case, the user has four single quotes on a line, wishfully hoping that the shell will match them up as outer quotes around a string with literal single quotes:

      ```sh
      #                   v--------match--------v
      alias server_uptime='ssh $host 'uptime -p''
      #                              ^--match--^
      ```

      The shell, meanwhile, always terminates single quoted strings at the first possible single quote:

      ```sh
      #                   v---match--v
      alias server_uptime='ssh $host 'uptime -p''
      #                                        ^^
      ```

      Which is the same thing as `alias server_uptime='ssh $host uptime' -p`.

      There is no way to nest single quotes. However, single quotes can be placed literally in double quotes, so we can instead concatenate a single quoted string and a double quoted string:

      ```sh
      #                   v--match---v
      alias server_uptime='ssh $host '"'uptime -p'"
      #                               ^---match---^
      ```

      This results in an alias with embedded single quotes.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2038:
  remediation_points: 50000
  content:
    body: |
      ## Use -print0/-0 or find -exec + to allow for non-alphanumeric filenames.

      ### Problematic code:

      ```sh
      find . -type f | xargs md5sum
      ```

      ### Correct code:

      ```sh
      find . -type f -print0 | xargs -0 md5sum
      ```

      ### Rationale:

      By default, `xargs` interprets spaces and quotes in an unsafe and unexpected way. Whenever it's used, it should be used with `-0` or `--null` to split on `\0` bytes, and `find` should be made to output `\0` separated filenames.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1090:
  remediation_points: 50000
  content:
    body: |
      ## Can't follow non-constant source. Use a directive to specify location.

      ### Problematic code:

      ```sh
      . "$(find_install_dir)/lib.sh"
      ```

      ### Correct code:

      ```sh
      # shellcheck source=src/lib.sh
      . "$(find_install_dir)/lib.sh"
      ```

      ### Rationale:

      ShellCheck is not able to include sourced files from paths that are determined at runtime. The file will not be read, potentially resulting in warnings about unassigned variables and similar.

      Use a [[Directive]] to point shellcheck to a fixed location it can read instead.

      ### Exceptions:

      If you don't care that ShellCheck is unable to account for the file, specify `# shellcheck source=/dev/null`.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2005:
  remediation_points: 50000
  content:
    body: |
      Useless `echo`? Instead of `echo $(cmd)`, just use `cmd`
      --------------------------------------------------------

      ### Problematic code:

      ```sh
      echo "$(cat 1.txt)"
      echo `< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c6`
      ```

      ### Correct code:

      ```sh
      cat 1.txt # In bash, but faster and still sticks exactly one newline: printf '%s\n' "$(<1.txt)"
      # The original `echo` sticks a newline; we want it too.
      < /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c6; echo
      ```

      ### Rationale

      The command substitution `$(foo)` yields the result of command `foo` with trailing newlines erased, and when it is passed to `echo` it generally just gives the same result as `foo`.

      ### Exceptions

      One may want to use command substitutions plus `echo` to make sure there is exactly one trailing newline. The special command substitution `$(<file)` in `bash` is also un-outline-able.

      Anyway, echo is still not that reliable (see [[SC2039#echo-flags]]) and `printf` should be used instead.

      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1099:
  remediation_points: 50000
  content:
    body: |
      ## You need a space before the #.

      ### Problematic code:

      ```sh
      while sleep 1
      do# show time
        date
      done
      ```

      ### Correct code:

      ```sh
      while sleep 1
      do # show time
        date
      done
      ```

      ### Rationale:

      ShellCheck has noticed that you have a keyword immediately followed by a `#`. In order for the `#` to start a comment, it needs to come after a word boundary such as a space.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2090:
  remediation_points: 50000
  content:
    body: |
      # Quotes/backslashes in this variable will not be respected.

      See companion warning, [[SC2089]].


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2107:
  remediation_points: 50000
  content:
    body: |
      ## Instead of [ a && b ], use [ a ] && [ b ].

      ### Problematic code:

      ```sh
      [ "$1" = "-v" && -z "$2" ]
      ```

      ### Correct code:

      ```sh
      [ "$1" = "-v" ] && [ -z "$2" ]
      ```

      ### Rationale:

      `&&` can not be used in a `[ .. ]` test expression. Instead, make two `[ .. ]` expressions and put the `&&` between them.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2097:
  remediation_points: 50000
  content:
    body: |
      ## This assignment is only seen by the forked process.

      ### Problematic code:

      ```sh
      name=World cmd -m "Hello $name"
      ```

      ### Correct code:

      ```sh
      export name=World
      cmd -m "Hello $name"
      ```

      To prevent setting the variable, this can also be done in a subshell:

      ```sh
      (
         export name=World
         cmd -m "Hello $name"
      ) # 'name' does not leave this subshell
      ```

      ### Rationale:

      In `name=World cmd "$name"`, `name=World` is passed in as part of the environment to `cmd` (i.e., in the `envp` parameter to [execve(2)](http://linux.die.net/man/2/execve)).  This means that `cmd` and its children will see the parameter, but no other processes will.

      However, `"$name"` is not expanded by `cmd`. `"$name"` is expanded by the shell before `cmd` is ever executed, and thus it will not use the new value.

      The solution is to set the variable and export the variable first. If limited scope is desired, a `( subshell )` can be used.

      ### Exceptions

      In the strange and fabricated scenarios where the script and a program uses a variable name for two different purposes, you can ignore this message. This is hard to conceive, since scripts should use lowercase variable names specifically to avoid collisions with the environment.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2161:
  remediation_points: 50000
  content:
    body: |
      ## Instead of '[ 1 ]', use 'true'.

      ### Problematic code:

      ```sh
      while [ 1 ]
      do
        echo "infinite loop"
      done
      ```

      ### Correct code:

      ```sh
      while true
      do
        echo "infinite loop"
      done
      ```

      ### Rationale:

      This is a stylistic suggestion to use `true` instead of `[ 1 ]`.

      `[ 1 ]` seems to suggest that the value "1" is somehow relevant to the statement. This is not the case: it doesn't matter. You can replace it with `[ 0 ]` or `[ wombat ]`, and it will still always be true.

      If you instead use `true`, the value is actually considered and can be inverted by replacing with `false`.

      On bash, you can also use `(( 1 ))`, which evaluates to true much like in C. `(( 0 ))` is similarly false.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2165:
  remediation_points: 50000
  content:
    body: |
      ## This nested loop overrides the index variable of its parent.

      And companion warning "This parent loop has its index variable overridden."

      ### Problematic code:

      ```sh
      for((i=0; i<10; i++))
      do
        for i in *
        do
          echo "$i"
        done
      done
      ```

      ### Correct code:

      ```sh
      for((i=0; i<10; i++))
      do
        for j in *
        do
          echo "$j"
        done
      done
      ```

      ### Rationale:

      When nesting loops, especially arithmetic for loops, using the same loop variable can cause unexpected results.

      In the problematic code, `i` will contain the last filename from the inner loop, which will be interpreted as a value in the next iteration out the outer loop. This results in either an infinite loop or a syntax error, depending on whether the last filename is a valid shell variable name.

      In nested for-in loops, variable merely shadow each other and won't cause infinite loops or syntax errors, but reusing the variable name is rarely intentional.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2103:
  remediation_points: 50000
  content:
    body: |
      # Use a ( subshell ) to avoid having to cd back.

      ### Problematic code:

      ```sh
      for dir in */
      do
        cd "$dir"
        convert index.png index.jpg
        cd ..
      done
      ```


      ### Correct code:

      ```sh
      for dir in */
      do
        (
        cd "$dir" || exit
        convert index.png index.jpg
        )
      done
      ```

      or

      ```sh
      for dir in */
      do
        cd "$dir" || exit
        convert index.png index.jpg
        cd ..
      done
      ```

      ### Rationale:

      When doing `cd dir; somestuff; cd ..`, `cd dir` can fail when permissions are lacking, if the dir was deleted, or if `dir` is actually a file.

      In this case, `somestuff` will run in the wrong directory and `cd ..` will take you to an even more wrong directory. In a loop, this will likely cause the next `cd` to fail as well, propagating this error and running these commands far away from the intended directories.

      Check `cd`s exit status and/or use subshells to limit the effects of `cd`.

      ### Exceptions

      If you set variables you can't use a subshell. In that case, you should definitely check the exit status of `cd`, which will also silence this suggestion.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2045:
  remediation_points: 50000
  content:
    body: |
      ## Iterating over ls output is fragile. Use globs.

      ### Problematic code:

          for f in $(ls *.wav)
          do
            echo "$f"
          done

      ### Correct code:

          for f in *.wav
          do
            [[ -e $f ]] || break  # handle the case of no *.wav files
            echo "$f"
          done

      Also note that in Bash, `shopt -s nullglob` will allow the loop to run 0 times instead of 1 if there are no matches. There are also [several other conditions](http://mywiki.wooledge.org/BashPitfalls#for_i_in_.24.28ls_.2A.mp3.29) to be aware of.

      ### Rationale:

      When looping over a set of files, it's always better to use globs when possible. Using command expansion causes word splitting and glob expansion, which will cause problems for certain filenames (typically first seen when trying to process a file with spaces in the name).

      The following files can or will break the first loop:

          touch 'filename with spaces.wav'
          touch 'filename with * globs.wav'
          touch 'More_Globs[2003].wav'
          touch 'files_with_fønny_chæracters_in_certain_locales.wav'


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2014:
  remediation_points: 50000
  content:
    body: |
      ## This will expand once before find runs, not per file found.

      ### Problematic code:

      ```sh
      find . -name '*.tar' -exec tar xf {} -C "$(dirname {})" \;
      ```

      ### Correct code:

      ```sh
      find . -name '*.tar' -exec sh -c 'tar xf "$1" -C "$(dirname "$1")"' _ {} \;
      ```

      ### Rationale:

      Bash evaluates any command substitutions before the command they feature in is executed. In this case, the command is `find`. This means that `$(dirname {})` will run **before** `find` runs, and not **while** `find` runs.

      To run shell code for each file, we can write a tiny script and inline it with `sh -c`. We add `_` as a dummy argument that becomes `$0`, and a filename argument that becomes `$1` in the inlined script:

      ```sh
      $ sh -c 'echo "$1 is in $(dirname "$1")"' _ "mydir/myfile"
      mydir/myfile is in mydir
      ```

      This command can be executed by `find -exec`, with `{}` as the filename argument. It executes shell which interprets the inlined script once for each file. Note that the inlined script is single quoted, again to ensure that the expansion does not happen prematurely .

      ### Exceptions:

      If you don't care (or if you prefer) that it's only expanded once, like when dynamically selecting the executable to be used by all invocations, you can ignore this message.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2082:
  remediation_points: 50000
  content:
    body: |
      ## To expand via indirection, use name="foo$n"; echo "${!name}".

      ### Problematic code:

      ```sh
      var_1="hello world"
      n=1
      echo "${var_$n}"
      ```

      ### Correct code:

      Bash/ksh:

      ```sh
      # Use arrays instead of dynamic names
      declare -a var
      var[1]="hello world"
      n=1
      echo "${var[n]}"
      ```

      or

      ```sh
      # Expand variable names dynamically
      var_1="hello world"
      n=1
      name="var_$n"
      echo "${!name}"
      ```

      POSIX sh:

      ```sh
      # Expand dynamically with eval
      var_1="hello world"
      n=1
      eval "tmp=\$var_$n"
      echo "${tmp}"
      ```

      ### Rationale:

      You can expand a variable `var_1` with `${var_1}`, but you can not generate the string `var_1` with an embedded expansion, like `${var_$n}`.

      Instead, if at all possible, you should use an array. Bash and ksh support both numerical and associative arrays, and an example is shown above.

      If you can't use arrays, you can indirectly reference variables by creating a temporary variable with its name, e.g. `myvar="var_$n"` and then expanding it indirectly with `${!myvar}`. This will give the contents of the variable `var_1`.

      If using POSIX sh, where neither arrays nor `${!var}` is available, `eval` can be used. You must be careful in sanitizing the data used to construct the variable name to avoid arbitrary code execution.

      ### Exceptions:

      None


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2092:
  remediation_points: 50000
  content:
    body: |
      ## Remove backticks to avoid executing output.

      Backticks does the same thing as `$(..)`. See [[SC2091]] for a description of the same problem with this syntax.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2021:
  remediation_points: 50000
  content:
    body: |
      ## Don't use [] around ranges in tr, it replaces literal square brackets.

      ### Problematic code:

      ```sh
      tr -cd '[a-z]'
      ```

      ### Correct code:

      ```sh
      tr -cd 'a-z'
      ```
      ### Rationale:

      Ancient System V `tr` required brackets around operands, but modern implementations including POSIX, GNU, OS X and *BSD instead treat them as literals.

      Unless you want to operate on literal square brackets, don't include them.

      ### Exceptions:

      If you do want to replace literal square brackets, reorder the expression (e.g. `a-z[]` to make it clear that the brackets are not special).

      ShellCheck does not warn about correct usage of `[..]` in character and equivalence classes like `[:lower:]` and `[=e=]`.

      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2167:
  remediation_points: 50000
  content:
    body: |
      ## This parent loop has its index variable overridden.

      See companion warning [[SC2165]].


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2172:
  remediation_points: 50000
  content:
    body: "## Trapping signals by number is not well defined. Prefer signal names.\n\n###
      Problematic code:\n\n```sh\ntrap myfunc 28\n```\n\n### Correct code:\n\n```sh\ntrap
      myfunc WINCH\n```\n### Rationale:\n\nSignal numbers can vary between platforms.
      Prefer signal names, which are fixed.\n\nSignal numbers 1, 2, 3, 6, 9, 14 and
      15 are specified as parts of the optional POSIX XSI and ShellCheck will not
      warn about these. \n\n### Exceptions:\n\nNone.\n\n### Notice\n\nOriginal content
      from the ShellCheck https://github.com/koalaman/shellcheck/wiki.\n"
SC1081:
  remediation_points: 50000
  content:
    body: |
      ## Scripts are case sensitive. Use 'if', not 'If'.

      ### Problematic code:

      ```sh
      If true
      Then
        echo "hello"
      Fi
      ```

      ### Correct code:

      ```sh
      if true
      then
        echo "hello"
      fi
      ```

      ### Rationale:

      Shells are case sensitive and do not accept `If` or `IF` in place of lowercase `if`.

      ### Exceptions

      If you're aware of this and insist on naming a function `WHILE`, you can quote the name to prevent shellcheck from thinking you meant `while`. Or if you really want the names, add things like `alias If=if IF=if` to replace those keywords and ask shellcheck to ignore them.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2035:
  remediation_points: 50000
  content:
    body: |
      # 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.

      For more information, see "[Filenames and Pathnames in Shell: How to do it Correctly](http://www.dwheeler.com/essays/filenames-in-shell.html)".


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2148:
  remediation_points: 50000
  content:
    body: |
      ##  Tips depend on target shell and yours is unknown. Add a shebang.

      ### Problematic code:

      ```sh
      echo "$RANDOM"   # Does this work
      ```

      ### Correct code:

      ```sh
      #!/bin/sh
      echo "$RANDOM"  # Unsupported in sh. Produces warning.
      ```

      or

      ```sh
      #!/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.
SC2017:
  remediation_points: 50000
  content:
    body: |
      ## Increase precision by replacing a/b\*c with a\*c/b.

      ### Problematic code:

      ```sh
      percent=$((count/total*100))
      ```

      ### Correct code:

      ```sh
      percent=$((count*100/total))
      ```

      ### Rationale:

      If integer division is performed before multiplication, the intermediate result will be truncated causing a loss of precision.

      In this case, if  `count=1` and `total=2`, then the problematic code results in `percent=0`, while the correct code gives `percent=50`.

      ### Exceptions:

      If you want and expect truncation you can ignore this message.

      ShellCheck doesn't warn when `b` and `c` are identical expressions, e.g. `a/10*10`, under the assumption that the intent is to rounded to the nearest 10 rather than the no-op of multiply by `1`.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2084:
  remediation_points: 50000
  content:
    body: |
      ## Remove '$' or use '_=$((expr))' to avoid executing output.

      ### Problematic code:

      ```sh
      i=4
      $(( i++ ))
      ```

      ### Correct code:

      Bash, Ksh:

      ```sh
      i=4
      (( i++ ))
      ```

      POSIX (assuming `++` is supported):

      ```sh
      i=4
      _=$(( i++ ))
      ```

      Alternative POSIX version that does not preserve the exit code:

      ```sh
      : $(( i++ ))
      ```

      ### Rationale:

      `$((..))` expands to a number. If it's the only word on the line, the shell will try to execute this number as a command name:

      ```sh
      $ i=4
      $ $(( i++ ))
      4: command not found
      $ echo $i
      5
      ```

      To avoid trying to execute the number as a command name, use one of the methods mentioned:

      ```sh
      $ i=4
      $ _=$(( i++ ))
      $ echo $i
      5
      ```

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2145:
  remediation_points: 50000
  content:
    body: |
      ## Argument mixes string and array. Use * or separate argument.

      ### Problematic code:

      ```sh
      printf "Error: %s\n" "Bad parameters: $@"
      ```

      ### Correct code:

      ```sh
      printf "Error: %s\n" "Bad parameters: $*"
      ```

      ### Rationale:

      The behavior when concatenating a string and array is rarely intended. The preceeding string is prefixed to the first array element, while the succeeding string is appended to the last one. The middle array elements are unaffected.

      E.g., with the parameters `foo`,`bar`,`baz`, `"--flag=$@"` is equivalent to the three arguments `"--flag=foo" "bar" "baz"`.

      If the intention is to concatenate all the array elements into one argument, use `$*`. This concatenates based on `IFS`.

      If the intention is to provide each array element as a separate argument, put the array expansion in its own argument.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2144:
  remediation_points: 50000
  content:
    body: |
      ##  -e doesn't work with globs. Use a for loop.

      ### Problematic code:

      ```sh
      if [ -e dir/*.mp3 ]
      then
        echo "There are mp3 files."
      fi
      ```

      ### Correct code:

      ```sh
      for file in dir/*.mp3
      do
        if [ -e "$file" ]
        then
          echo "There are mp3 files"
          break
        fi
      done
      ```

      ### Rationale:

      `[ -e file* ]` only works if there's 0 or 1 matches. If there are multiple, it becomes `[ -e file1 file2 ]`, and the test fails.

      `[[ -e file* ]]` doesn't work at all.

      Instead, use a for loop to expand the glob and check each result individually.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1015:
  remediation_points: 50000
  content:
    body: |
      ## This is a unicode double quote. Delete and retype it.

      ### Problematic code:

      ```sh
      echo “hello world”
      ```

      ### Correct code:

      ```sh
      echo "hello world"
      ```

      ### Rationale:

      Blog software and word processors frequently replaces ASCII quotes `""` with fancy Unicode quotes, `“”`. To bash, Unicode quotes are considered regular literals and not quotes at all.

      Simply delete them and retype them in your editor.

      ### Exceptions

      If you really want literal Unicode double quotes, you can put them in single quotes (or unicode single quotes in double quotes) to make shellcheck ignore them.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1072:
  remediation_points: 50000
  content:
    body: |
      # Unexpected ..

      See [Parser Error](Parser Error).


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2040:
  remediation_points: 50000
  content:
    body: |
      ## #!/bin/sh was specified, so ____ is not supported, even when sh is actually bash.

      The shebang indicates that the script works with `/bin/sh`, but you are using non-standard features that may not work with `/bin/sh`, **even if /bin/sh is actually bash**. Bash behaves differently when invoked as `sh`, and disabling support for the highlighted feature is one part of that.

      Specify `#!/usr/bin/env bash` to ensure that bash (or your shell of choice) will be used, or rewrite the script to be more portable.

      The Ubuntu wiki has [a list of portability issues](https://wiki.ubuntu.com/DashAsBinSh) and suggestions on how to rewrite them.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2150:
  remediation_points: 50000
  content:
    body: |
      ## -exec does not automatically invoke a shell. Use -exec sh -c .. for that.

      ### Problematic code:

      ```sh
      find . -type f -exec 'cat {} | wc -l' \;
      ```

      ### Correct code:

      ```sh
      find . -type f -exec sh -c 'cat {} | wc -l' \;         # Insecure
      find . -type f -exec sh -c 'cat "$1" | wc -l' _ {} \;  # Secure
      ```

      Sometimes the command can also be rewritten to not require `find` to invoke a shell:

      ```sh
      find . -type f -exec wc -l {} \; | cut -d ' ' -f 1
      ```

      ### Rationale:

      find `-exec` and `-execdir` uses `execve(2)` style semantics, meaning it expects an executable and zero or more arguments that should be passed to it.

      It does not use `system(3)` style semantics, meaning it does not accept a shell command as a string, to be parsed and evaluated by the system's command interpreter.

      If you want `find` to execute a shell command, you have to specify `sh` (or `bash`) as the executable, `-c` as first argument and your shell command as the second.

      To prevent command injection, the filename can be passed as a separate argument to sh and referenced as a positional parameter.

      ### Exceptions

      This warning would trigger falsely if executing a program with spaces in the path, if no other arguments were specified.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2095:
  remediation_points: 50000
  content:
    body: "## Add < /dev/null to prevent ssh from swallowing stdin.\n\nThe same error
      applies to multiple commands, like `ffmpeg` and `mplayer`.\n\n### Problematic
      code:\n\n```sh\nwhile read -r host\ndo\n  ssh \"$host\" \"uptime\"\ndone < hosts.txt\n```\n\n###
      Correct code:\n\n```sh\nwhile read -r host\ndo\n  ssh \"$host\" \"uptime\" <
      /dev/null\ndone < hosts.txt\n```\n### Rationale:\n\nCommands that process stdin
      will compete with the `read` statement for input. This is especially tricky
      for commands you wouldn't expect reads from stdin, like `ssh .. uptime`, `ffmpeg`
      and `mplayer`.\n\nThe most common symptom of this is a `while read` loop only
      running once, even though the input contains many lines. The is because the
      rest of the lines are swallowed by the offending command.\n\nTo refuse such
      commands input, redirect their stdin with `< /dev/null`. \n\n### Exceptions:\n\nNone.\n\n###
      Notice\n\nOriginal content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.\n"
SC2010:
  remediation_points: 50000
  content:
    body: |
      ## Don't use ls | grep. Use a glob or a for loop with a condition to allow non-alphanumeric filenames.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1089:
  remediation_points: 50000
  content:
    body: |
      ## Parsing stopped here. Is this keyword correctly matched up?

      ### Problematic code:

      ```sh
      if true
      then
        echo hello
      fi
      fi
      ```

      ### Correct code:

      ```sh
      if true
      then
        echo hello
      fi
      ```

      ### Rationale:

      This error is typically seen when there are too many `fi`, `done` or `esac`s, or when there's a `do` or `then` without a corresponding `while`, `for` or `if`. This is often due to deleting a loop or conditional statement but not its terminator.

      In some cases, it can even be caused by bad quoting:

      ```sh
      var="foo
      if [[ $var = "bar ]
      then
        echo true
      fi
      ```

      In this case, the `if` ends up inside the double quotes, leaving the `then` dangling.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2108:
  remediation_points: 50000
  content:
    body: |
      ## In [\[..]], use && instead of -a.

      ### Problematic code:

      ```sh
      [[ "$1" = "-v" -a -z "$2" ]]
      ```

      ### Correct code:

      ```sh
      [[ "$1" = "-v" && -z "$2" ]]
      ```

      ### Rationale:

      `-a` for logical AND is not supported in a `[[ .. ]]` expression. Use `&&` instead.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1095:
  remediation_points: 50000
  content:
    body: |
      ## You need a space or linefeed between the function name and body.

      ### Problematic code:

      ```sh
      function foo{
        echo "hello world"
      }
      ```

      ### Correct code:

      Prefer POSIX syntax:
      ```sh
      foo() {
        echo "hello world"
      }
      ```

      Alternatively, add the missing space between function name and opening `{`:
      ```sh
      #           v-- Here
      function foo {
        echo "hello world"
      }
      ```
      ### Rationale:

      When using `function` keyword function definitions without `()`, a space is required between the function name and the opening `{`.

      ### Exceptions:

      None.

      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2033:
  remediation_points: 50000
  content:
    body: |
      # Shell functions can't be passed to external commands.

      ### Problematic code:

      ```sh
      foo() { bar --baz "$@"; frob --baz "$@"; };
      find . -exec foo {} +
      ```

      ### Correct code:

      ```sh
      find . -exec sh -c 'bar --baz "$@"; frob --baz "$@";' -- {} +
      ```

      ### Rationale:

      Shell functions are only known to the shell. External commands like `find`, `xargs`, `su` and `sudo` do not recognize shell functions.

      Instead, the function contents can be executed in a shell, either through `sh -c` or by creating a separate shell script as an executable file.

      ### Exceptions

      If you're intentionally passing a word that happens to have the same name as a declared function, you can quote it to make shellcheck ignore it, e.g.

      ```sh
      nobody() {
        sudo -u "nobody" "$@"
      }

      ```


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2125:
  remediation_points: 50000
  content:
    body: |
      ## Brace expansions and globs are literal in assignments. Quote it or use an array.

      ### Problematic code:

      ```sh
      foo={1..9}
      echo $foo
      ```

      ### Correct code:

      ```sh
      foo=( {1..9} )
      echo "${foo[@]}"
      ```

      ### Rationale:

      `echo *.png {1..9}` expands to all png files and numbers from 1 to 9, but `var=*.png` or `var={1..9}` will just assign the literal strings `'*.png'` and `'{1..9}'`.

      To make the variable contain all png files or 1 through 9, use an array as demonstrated.

      If you intended to assign these values as literals, quote them (e.g. `var="*.png"`).

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2044:
  remediation_points: 50000
  content:
    body: |
      ## For loops over find output are fragile. Use find -exec or a while read loop.

      ### Problematic code:

      ```sh
      for file in $(find mydir -mtime -7 -name '*.mp3')
      do
        let count++
        echo "Playing file no. $count"
        play "$file"
      done
      echo "Played $count files"
      ```

      This will fail for filenames containing spaces and similar, such as `My File.mp3`, and has a series of potential globbing issues depending on other filenames in the directory like (if you have `MyFile2.mp3` and `MyFile[2014].mp3`, the former file will play twice and the latter will not play at all).

      ### Correct code:

      There are many possible fixes, each with its pros and cons.

      The most general fix (that requires the least amount of thinking to apply) is having `find` output a `\0` separated list of files and consuming them in a `while read` loop:

      ```sh
      while IFS= read -r -d '' file
      do
        let count++
        echo "Playing file no. $count"
        play "$file"
      done <   <(find mydir -mtime -7 -name '*.mp3' -print0)
      echo "Played $count files"
      ```

      In usage it's very similar to the `for` loop: it gets its output from a `find` statement, it executes a shell script body, it allows updating/aggregating variables, and the variables are available when the loop ends.

      It requires Bash, and works with GNU, Busybox, OS X, FreeBSD and OpenBSD find, but not POSIX find.

      ##### If `find` is just matching globs recursively

      If you don't need `find` logic like `-mtime -7` and just use it to match globs recursively (all `*.mp3` files under a directory), you can instead use `globstar` and `nullglob` instead of `find`, and still use a `for` loop:

      ```sh
      shopt -s globstar nullglob
      for file in mydir/**/*.mp3
      do
        let count++
        echo "Playing file no. $count"
        play "$file"
      done
      echo "Played $count files"
      ```

      This is bash 4 specific.


      ##### For POSIX

      If you need POSIX compliance, this is a fair approach:

      ```sh
      find mydir ! -name "$(printf "*\n*")" -name '*.mp3' > tmp
      while IFS= read -r file
      do
        let count++
        echo "Playing file #$count"
        play "$file"
      done < tmp
      rm tmp
      echo "Played $count files"
      ```

      The only problem is for filenames containing line feeds. A `! -name "$(printf "*\n*")"` has been added to simply skip these files, just in case there are any.

      If you don't need variables to be available after the loop (here, if you don't need to print the final play count at the end), you can skip the `tmp` file and just pipe from `find` to `while`.

      ##### For simple commands with no aggregation

      If you don't need a shell script loop body or any form of variable  like if we only wanted to play the file, we can dramatically simplify while maintaining POSIX compatibility:

      ```sh
      # Simple and POSIX
      find mydir -name '*.mp3' -exec play {} \;
      ```

      This does not allow things like `let counter++` because `let` is a shell builtin, not an external command.

      ##### For shell commands with no aggregation

      If we do need a shell script body but no aggregation, you can do the above but invoking `sh` (this is still POSIX):

      ```sh
      find mydir -name '*.mp3' -exec sh -c '
          echo "Playing ${1%.mp3}"
          play "$1"
        ' sh {} \;
      ```

      This would not be possible without `sh`, because `${1%.mp3}` is a shell construct that `find` can't evaluate by itself. If we had tried to `let counter++` in this loop, we would have found that the value never changes.

      Note that using `+` instead of `\;`, and using an embedded `for file in "$@"` loop rather than `"$1"`, will not allow aggregating variables. This is because for large lists, `find` will invoke the command multiple times, each time with some chunk of the input.


      ### Rationale:

      `for var in $(find ...)`  loops rely on word splitting and will evaluate globs, which will wreck havoc with filenames containing whitespace or glob characters.

      `find -exec` `for i in glob` and `find`+`while` do not rely on word splitting, so they avoid this problem.

      ### Exceptions

      If you know about and carefully apply `IFS=$'\n'` and `set -f`, you could choose to ignore this message.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2156:
  remediation_points: 50000
  content:
    body: |
      ## Injecting filenames is fragile and insecure. Use parameters.

      ### Problematic code:

      ```sh
      find . -name '*.mp3' -exec sh -c 'i="{}"; sox "$i" "${i%.mp3}.wav"' \;
      ```

      ### Correct code:

      ```sh
      find . -name '*.mp3' -exec sh -c 'i="$1"; sox "$i" "${i%.mp3}.wav"' _ {} \;
      ```

      ### Rationale:

      In the problematic example, the filename is passed by injecting it into a shell string. Any shell metacharacters in the filename will be interpreted as part of the script, and not as part of the filename. This can break the script and allow arbitrary code execution exploits.

      In the correct example, the filename is passed as a parameter. It will be safely treated as literal text. The `_` is a dummy string that becomes `$0` in the script.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1001:
  remediation_points: 50000
  content:
    body: |
      ## This `\c` will be a regular 'c' in this context.

      ### Problematic code:

      ```sh
      echo Yay \o/
      \git status # Non-POSIX way to suppress aliases
      ```

      ### Correct code:

      ```sh
      echo 'Yay \o/'
      command git status
      ```

      ### Rationale:

      Escaping something that doesn't need escaping sometimes indicates a bug.

      If the backslash was supposed to be literal, single quote it.

      If the purpose is to run an external command rather than an alias, prefer `command`.

      ### Exceptions

      If you have an alias and a function (as opposed to an external command), you can either ignore this message or use `"name"` instead of `\name` to quiet ShellCheck.

      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2128:
  remediation_points: 50000
  content:
    body: |
      ## Expanding an array without an index only gives the first element.

      ### Problematic code:

      ```sh
      myarray=(foo bar)
      for f in $myarray
      do
        cat "$f"
      done
      ```

      ### Correct code:

      ```sh
      myarray=(foo bar)
      for f in "${myarray[@]}"
      do
        cat "$f"
      done
      ```

      ### Rationale:

      When referencing arrays, `$myarray` is equivalent to `${myarray[0]}` -- it results in only the first of multiple elements.

      To get all elements as separate parameters, use the index `@` (and make sure to double quote). In the example, `echo "${myarray[@]}"` is equivalent to `echo "foo" "bar"`.

      To get all elements as a single parameter, concatenated by the first character in `IFS`, use the index `*`. In the example, `echo "${myarray[*]}"` is equivalent to `echo "foo bar"`.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2153:
  remediation_points: 50000
  content:
    body: |
      ## Possible Misspelling: MYVARIABLE may not be assigned, but MY_VARIABLE is.

      ### Problematic code:

      ```sh
      MY_VARIABLE="hello world"
      echo "$MYVARIABLE"
      ```

      ### Correct code:

      ```sh
      MY_VARIABLE="hello world"
      echo "$MY_VARIABLE"
      ```

      ### Rationale:

      ShellCheck has noticed that you reference a variable that is not assigned in the script, which has a name remarkably similar to one that is explicitly assigned. You should verify that the variable name is spelled correctly.

      Note: This error only triggers for environment variables (all uppercase variables), and only when they have names similar to something assigned in the script. If the variable is script-local, it should by convention have a lowercase name, and will in that case be caught by [SC2154] whether or not it resembles another name.

      ### Exceptions:

      If you've double checked and ensured that you did not intend to reference the specified variable, you can disable this message with a [[directive]]. The message will also not appear for guarded references like `${ENVVAR:-default}` or `${ENVVAR:?Unset error message here}`.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2043:
  remediation_points: 50000
  content:
    body: |
      ## This loop will only run once, with var=value

      ### Problematic code:

      ```sh
      for var in value
      do
        echo "$var"
      done
      ```

      ### Correct code:

      Correct code depends on what you want to do.

      To iterate over files in a directory, instead of `for var in /my/dir` use:

      ```sh
      for var in /my/dir/* ; do echo "$var"; done
      ```

      To iterate over lines in a file or command output, use a while read loop instead:

      ```sh
      mycommand | while IFS= read -r line; do echo "$line"; done
      ```

      To iterate over *words* written to a command or function's stdout, instead of `for var in myfunction`, use

      ```sh
      for var in $(myfunction); do echo "$var"; done
      ```

      To iterate over *words* in a variable, instead of  `for var in myvariable`, use

      ```sh
      for var in $myvariable; do echo "$var"; done
      ```



      ### Rationale:

      ShellCheck has detected that your for loop iterates over a single, constant value. This is most likely a bug in your code, caused by you not expanding the value in the way you want.

      You should make sure that whatever you loop over will expand into multiple words.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1045:
  remediation_points: 50000
  content:
    body: |
      # It's not 'foo &; bar', just 'foo & bar'.

      ### Problematic code:

      ```sh
      foo &; bar
      ```

      ### Correct code:

      ```sh
      foo & bar
      ```

      ### Rationale:

      Both `&` and `;` terminate the command. You should only use one of them.



      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2041:
  remediation_points: 50000
  content:
    body: |
      ## This is a literal string. To run as a command, use $(seq 1 10)

      ### Problematic code:

      ```sh
      for i in 'seq 1 10'
      do
        echo "$i"
      done
      ```

      ### Correct code:

      ```sh
      for i in $(seq 1 10)
      do
        echo "$i"
      done
      ```

      ### Rationale:

      The intent was to run the code in the single quotes. This would have worked with slanted backticks, `` `..` ``, but here the very similar looking single quotes `'..'` were used, resulting in a string literal instead of command output.

      This is one of the many problems with backticks, so it's better to use `$(..)` to expand commands.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2016:
  remediation_points: 50000
  content:
    body: |
      # Expressions don't expand in single quotes, use double quotes for that.

      ### Problematic code:

      ```sh
      name=World
      echo 'Hello $name'
      ```

      ### Correct code:

      ```sh
      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:

      ```sh
      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".


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2159:
  remediation_points: 50000
  content:
    body: |
      ## [ 0 ] is true. Use 'false' instead

      ### Problematic code:

      ```sh
      if [ 0 ]
      then
        echo "always triggers"
      fi
      ```

      ### Correct code:

      ```sh
      if false
      then
        echo "never triggers"
      fi
      ```

      ### Rationale:

      `[ str ]` checks whether `str` is non-empty. It doesn't matter if `str` is `0`, it will still be evaluated for non-emptyness.

      Instead, use the command `false` which -- as the manual puts it -- does nothing, unsuccessfully.

      ### Exceptions:

      None


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2149:
  remediation_points: 50000
  content:
    body: |
      ## Remove $/${} for numeric index, or escape it for string.

      ### Problematic code:

      ```sh
      # Regular array
      index=42
      echo $((array[$index]))
      ```

      or

      ```sh
      # Associative array
      index=banana
      echo $((array[$index]))
      ```

      ### Correct code:

      # Regular array
      index=42
      echo $((array[index]))
      ```

      or

      ```sh
      # Associative array
      index=banana
      echo $((array[\$index]))
      ```

      ### Rationale:

      For a numerically indexed array, the `$` is mostly pointless and can be removed like in [[SC2004]].

      For associative arrays, the `$` should be escaped to avoid accidental dereferencing:

      ```sh
      declare -A array
      index='$1'
      array[$index]=42
      echo "$(( array[$index] ))"    # bash: array: bad array subscript
      echo "$(( array[\$index] ))"   # 42
      ```

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2087:
  remediation_points: 50000
  content:
    body: |
      ## Quote 'EOF' to make here document expansions happen on the server side rather than on the client.

      ### Problematic code:

      ```sh
      ssh host.example.com << EOF
        echo "Logged in on $HOSTNAME"
      EOF

      ### Correct code:

      ```sh
      ssh host.example.com << "EOF"
        echo "Logged in on $HOSTNAME"
      EOF
      ```

      ### Rationale:

      When the end token of a here document is unquoted, parameter expansion and command substitution will happen on in contents of the here doc.

      This means that before sending the commands to the server, the client replaces `$HOSTNAME` with localhost, thereby sending `echo "Logged in on localhost"` to the server. This has the effect of printing the client's hostname instead of the server's.

      Scripts with any kind of variable use are especially problematic because all references will be expanded before the script run. For example,

      ```sh
      ssh host << EOF
        x="$(uname -a)"
        echo "$x"
      EOF
      ```

      will never print anything, neither client nor server details, since before evaluation, it will be expanded to:

      ```sh
        x="Linux localhost ... x86_64 GNU/Linux"
        echo ""
      ```

      By quoting the here token, local expansion will not take place, so the server sees `echo "Logged in on $HOSTNAME"` which is expanded and printed with the server's hostname, which is usually the intention.

      ### Exceptions:

      If the client should expand some or all variables, this message can and should be ignored.

      To expand a mix of local and remote variables, the here doc end token should be unquoted, and the remote variables should be escaped, e.g.

      ```sh
      ssh host.example.com << EOF
        echo "Logged in on \$HOSTNAME from $HOSTNAME"
      EOF
      ```


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1077:
  remediation_points: 50000
  content:
    body: |
      # For command expansion, the tick should slant left (` vs ´).


      ### Problematic code:

      ```sh
      echo "Your username is ´whoami´"
      ```

      ### Correct code:

      ```sh
      echo "Your username is $(whoami)" # Preferred
      echo "Your username is `whoami`"  # Deprecated, will give [SC2006]
      ```

      ### Rationale:

      In some fonts it's hard to tell ticks apart, but Bash strongly distinguishes between backticks (grave accent `` ` ``), forward ticks (acute accent `´`) and regular ticks (apostrophe `'`).

      Backticks start command expansions, while forward ticks are literal. To help spot bugs, ShellCheck parses backticks and forward ticks interchangeably.

      ### Exceptions

      If you want to write out literal forward ticks, such as fancyful ascii quotation marks:

      ```sh
      echo "``Proprietary software is an injustice.´´  - Richard Stallman"
      ```

      use single quotes instead:

      ```sh
      echo '``Proprietary software is an injustice.´´  - Richard Stallman'
      ```

      To nest forward ticks in command expansion, use `$(..)` instead of `` `..` ``.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2009:
  remediation_points: 50000
  content:
    body: |
      ## SC2009 Consider using pgrep instead of grepping ps output.

      ### Problematic Code:

      ```sh
      ps ax | grep -v grep | grep "$service" > /dev/null
      ```

      ### Correct Code:

      ```sh
      pgrep -f "$service" > /dev/null
      ```

      ### Rationale:

      If you are just after a pid from a running program, then pgrep is a much safer alternative. Especially if you are also looking for a pid belonging to a certain user or group. All of the parameters are in one command and it cat eliminate multiple greps, cuts, seds, awks, ect.

      ### Exceptions

      What if you have the pid and you are looking for the matching program name?

      ```sh
      pid=123; ps ax | grep "$pid"
      ```

      What if you want a range of the ps field, like from the 16th space to the end of the line?

      ```sh
      ps ax | grep "$pid" | cut -d" " -f16-
      ```

      Both are valid cases where SC2009 is not valid.



      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2098:
  remediation_points: 50000
  content:
    body: |
      ## This expansion will not see the mentioned assignment.

      See companion warning [[SC2097]].


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2066:
  remediation_points: 50000
  content:
    body: |
      ## Since you double quoted this, it will not word split, and the loop will only run once.

      ### Problematic code:

      ```sh
      for s in "$(mycommand)"; do echo "$s"; done
      ```

      ### Correct code:

      The correct code depends on your intention. Let's say you're in a directory with the files `file.png` and `My cat.png`, and you want to loop over a command that outputs (or variable that contains):

      ```sh
      hello world
      My *.png
      ```

      #### Loop over each line without globbing (`hello world`, `My *.png`)

      ```sh
      mycommand | while IFS= read -r s; do echo "$s"; done
      ```

      #### Loop over each word with globbing (`hello`, `world`, `My`, `file.png`, `My cat.png`):

      ```sh
      # relies on the fact that IFS by default contains space-tab-linefeed
      for s in $(mycommand); do echo "$s"; done
      ```

      #### Loop over each line with globbing (`hello world`, `My cat.png`)

      ```sh
      # explicitly set IFS to contain only a line feed
      IFS='
      '
      for s in $(mycommand); do echo "$s"; done
      ```

      ### Rationale:

      You get this warning because you have a loop that will only ever run exactly one iteration. Since you have a loop, you clearly expect it to run more than once. You just have to decide how it should be split up.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2169:
  remediation_points: 50000
  content:
    body: "## In dash, [\\[ ]] is not supported.\n\nYou are writing a script for `dash`,
      but you're using a feature that `dash` doesn't support (in this case, bash/ksh
      style `[[ .. ]]` conditions). \n\nSee Ubuntu's [DashAsBinSh](https://wiki.ubuntu.com/DashAsBinSh)
      migration guide for how to make bash-specific scripts dash-compatible.\n\n###
      Notice\n\nOriginal content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.\n"
SC2121:
  remediation_points: 50000
  content:
    body: |
      # To assign a variable, use just 'var=value', no 'set ..'.

      ### Problematic code:

      ```sh
      set var=42
      set var 42
      ```

      ### Correct code:

      ```sh
      var=42
      ```

      ### Rationale:

      `set` is not used to set or assign variables in Bourne shells. It's used to set shell options and positional parameters.

      To assign variables, use `var=value` with no `set` or other qualifiers.

      ### Exceptions

      If you actually do want to set positional parameters, simply quoting them or using `--` will make shellcheck stop warning, e.g. `set -- var1 var2` or `set "foo=bar"`.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2036:
  remediation_points: 50000
  content:
    body: |
      ## If you wanted to assign the output of the pipeline, use a=$(b | c) .

      ### Problematic code:

      ```sh
      sum=find | wc -l
      ```

      ### Correct code:

      ```sh
      sum=$(find | wc -l)
      ```

      ### Rationale:

      The intention in this code was that `sum` would in some way get the value of the command `find | wc -l`.

      However, `|` has precedence over the `=`, so the command is a two stage pipeline consisting of `sum=find` and `wc -l`.

      `sum=find` is a plain string assignment. Since it happens by itself in an independent pipeline stage, it has no effect: it produces no output, and the variable disappears when the pipeline stage finishes. Because the assignment produces no output, `wc -l` will count 0 lines.

      To instead actually assign a variable with the output of a command, command substitution `$(..)` can be used.

      ### Exceptions:

      None. This warning is triggered whenever the first stage of a pipeline is a single assignment, which is never correct.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2086:
  remediation_points: 50000
  content:
    body: |
      #Double quote to prevent globbing and word splitting.

      ### Problematic code:

      ```sh
      echo $1
      for i in $*; do :; done # this one and the next one also applies to expanding arrays.
      for i in $@; do :; done
      ```

      ### Correct code:

      ```sh
      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:

      ```sh
      $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:

      ```sh
      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.

      ```sh
      options="-j 5 -B"
      make $options file
      ```

      Just quoting this doesn't work. Instead, you should have used an array (bash, ksh, zsh):

      ```bash
      options=(-j 5 -B) # ksh: set -A options -- -j 5 -B
      make "${options[@]}" file
      ```

      or a function (POSIX):

      ```sh
      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=''`.



      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2008:
  remediation_points: 50000
  content:
    body: |
      ## echo doesn't read from stdin, are you sure you should be piping to it?

      ### Problematic code:

      ```sh
      find . | echo
      ```

      ### Correct code:

      ```sh
      find .
      ```

      ### Rationale:

      You are piping command output to `echo`, but `echo` ignores all piped input.

      In particular, `echo` is not responsible for putting output on screen. Commands already output data, and with no further actions that will end up on screen.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1044:
  remediation_points: 50000
  content:
    body: "**COULDN'T FIND THE END OF THE HERE DOC.** The starting Here tag must match
      the closing Here tag. \n\n### Notice\n\nOriginal content from the ShellCheck
      https://github.com/koalaman/shellcheck/wiki.\n"
SC2114:
  remediation_points: 50000
  content:
    body: |
      ## Warning: deletes a system directory. Use 'rm --' to disable this message.

      ### Problematic code:

      ```sh
      rm -rf /usr /lib/nvidia-current/xorg/xorg
      ```

      ### Correct code:

      ```sh
      rm -rf /usr/lib/nvidia-current/xorg/xorg
      ```

      ### Rationale:

      The example line of code was an actual bug in the [Bumblebee NVIDIA driver](https://github.com/MrMEEE/bumblebee-Old-and-abbandoned/commit/a047be85247755cdbe0acce6f1dafc8beb84f2ac).

      Due to an accidental space, it deleted `/usr` instead of just the particular directory.

      ### Exceptions:

      In cases of chroot, initramfs and similar, it's reasonable to delete otherwise important directories. Due to this, Shellcheck will not warn if the command contains `--`:

      ```sh
      rm -rf -- /usr
      ```

      This is an arbitrary convention to allow deleting such directories without having to use a [[directive]] to silence the warning.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2062:
  remediation_points: 50000
  content:
    body: |
      # Quote the grep pattern so the shell won't interpret it.

      ### Problematic code
          grep foo* file

      ### Correct code
          grep "foo*" file

      ### Rationale
      The regex passed to grep frequently contains characters that collide with globs. The code above is supposed to match "f followed by 1 or more o's", but if the directory contains a file called "foo.txt", an unquoted pattern will cause it to become `grep foo.txt file`.

      To prevent this, always quote the regex passed to grep, especially when it contains one or more glob character.

      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1016:
  remediation_points: 50000
  content:
    body: |
      ## This is a unicode single quote. Delete and retype it.

      ### Problematic code:

      ```sh
      echo ‘hello world’
      ```

      ### Correct code:

      ```sh
      echo 'hello world'
      ```

      ### Rationale:

      Some software, like OS X, Word and Wordpress, may automatically replace your regular quotes with slanted unicode quotes. Try deleting and retyping them, and/or disable "smart quotes" in your editor or OS.

      ### Exceptions

      None


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1018:
  remediation_points: 50000
  content:
    body: |
      # This is a unicode non-breaking space. Delete it and retype as space.

      You copy-pasted some code, probably from a blog or web site, which for formatting reasons contained unicode no-break spaces or unicode zero-width spaces instead of regular spaces or in words.

      To humans, a zero-width space is invisible and a non-breaking space is indistinguishable from a regular space, but the shell does not agree.

      If you have just a few, delete the indiciated space/word and retype it. If you have tons, do a search&replace in your editor (copy-paste an offending space into the search field, and type a regular space into the replace field), or use `sed -e $'s/\xC2\xA0/ /g' -e $'s/\xE2\x80\x8b//g' -i yourfile` to remove them.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1083:
  remediation_points: 50000
  content:
    body: |
      ## This `{`/`}` is literal. Check expression (missing `;/\n?`) or quote it.

      ### Problematic code:

      ```sh
      rmf() { rm -f "$@" }
      ```

      or

      ```sh
      eval echo \${foo}
      ```

      ### Correct code:

      ```sh
      rmf() { rm -f "$@"; }
      ```

      and

      ```sh
      eval "echo \${foo}"
      ```

      ### Rationale:

      Curly brackets are normally used as syntax in parameter expansion, command grouping and brace expansion.

      However, if they don't appear alone at the start of an expression or as part of a parameter or brace expansion, the shell silently treats them as literals. This frequently indicates a bug, so ShellCheck warns about it.

      In the example function, the `}` is literal because it's not at the start of an expression. We fix it by adding a `;` before it.

      In the example eval, the code works fine. However, we can quiet the warning and follow good practice by adding quotes around the literal data.

      ShellCheck does not warn about `{}`, since this is frequently used with `find` and rarely indicates a bug.

      ### Exceptions

      This error is harmless when the curly brackets are supposed to be literal, in e.g. `awk {'print $1'}`. However, it's cleaner and less error prone to simply include them inside the quotes: `awk '{print $1}'`.

      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2143:
  remediation_points: 50000
  content:
    body: |
      ## Use grep -q instead of comparing output with [ -n .. ].
      ### Problematic code:

      ```sh
      if [ "$(find . | grep 'IMG[0-9]')" ]
      then
        echo "Images found"
      fi
      ```

      ### Correct code:

      ```sh
      if find . | grep -q 'IMG[0-9]'
      then
        echo "Images found"
      fi
      ```

      ### Rationale:

      The problematic code has to iterate the entire directory and read all matching lines into memory before making a decision.

      The correct code is cleaner and stops at the first matching line, avoiding both iterating the rest of the directory and reading data into memory.

      ### Exceptions

      The `pipefail` bash option may interfere with this rewrite, since the `if` will now in effect be evaluating the statuses of all commands instead of just the last one. Be careful using them together.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1094:
  remediation_points: 50000
  content:
    body: |
      ## Parsing of sourced file failed. Ignoring it.

      ### Problematic code:

      ```sh
      source mylib
      ```

      ### Correct code:

      ```sh
      # shellcheck disable=SC1094
      source mylib
      ```

      (or fix `mylib`)

      ### Rationale:

      ShellCheck encountered a parsing error in a sourced file, `mylib` in the example.

      Fix parsing error, or just disable it with a directive.

      ### Exceptions:

      If the file is fine and this is due to a known `shellcheck` bug, you can ignore it with a [[directive]] as in the example.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1086:
  remediation_points: 50000
  content:
    body: |
      ## Don't use $ on the iterator name in for loops.

      ### Problematic code:

      ```sh
      for $var in *
      do
        echo "$var"
      done
      ```

      ### Correct code:

      ```sh
      for var in *
      do
        echo "$var"
      done
      ```

      ### Rationale:

      The variable is named `var`, and can be expanded to its value with `$var`.

      The `for` loop expects the variable's name, not its value (and the name can not be specified indirectly).

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2077:
  remediation_points: 50000
  content:
    body: |
      ## You need spaces around the comparison operator.

      ### Problematic code:

      ```sh
      [[ 0=1 ]]
      ```

      ### Correct code:

      ```sh
      [[ 0 = 1 ]]
      ```

      ### Rationale:

      `[[ 0 = 1 ]]` means "check if 0 and 1 are equal".

      `[[ str ]]` is short form for `[[ -n str ]]`, and means "check if `str` is non-empty". It doesn't matter if `str` happens to contain `0=1`.

      Always use spaces around the comparison operator in `[..]` and `[[..]]`, otherwise it won't be recognized as an operator.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2170:
  remediation_points: 50000
  content:
    body: |
      ## Numerical -eq does not dereference in [..]. Expand or use string operator.

      ### Problematic code:

      ```sh
      read -r n
      if [ n -lt 0 ]
      then
         echo "bad input"
      fi
      ```

      ### Correct code:

      ```sh
      read -r n
      if [ "$n" -lt 0 ]
      then
         echo "bad input"
      fi
      ```
      ### Rationale:

      You are comparing a string value with a numerical operator, such as `-eq`, `-ne`, `-lt` or `-gt`.

      In `[[ .. ]]`, this would automatically dereference the string, looking to see if there are variables by that name.

      In `[ .. ]`, which you are using, the string is just treated as an invalid number.

      If you want to compare numbers, expand yourself (e.g. use `$var` instead of `var`). If you are trying to compare strings and not numbers, use `=`, `!=` `\<` or `\>` instead.

      ### Exceptions:

      None.

      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2051:
  remediation_points: 50000
  content:
    body: "## Bash doesn't support variables in brace range expansions.\r\n\r\n###
      Problematic code:\r\n\r\nfor i in {1..$n}\r\ndo\r\n  echo \"$i\"\r\ndone\r\n\r\n###
      Correct code:\r\n\r\nfor ((i=0; i<n; i++))\r\ndo\r\n  echo \"$i\"\r\ndone\r\n\r\n###
      Rationale:\r\n\r\nIn Bash, brace expansion happens before variable expansion.
      This means that brace expansion will not account for variables.\r\n\r\nFor integers,
      use an arithmetic for loop instead. For zero-padded numbers or letters, use
      of eval may be warranted:\r\n\r\nfrom=\"a\" to=\"m\"\r\nfor c in $(eval \"echo
      {$from..$to}\"); do echo \"$c\"; done\r\n\r\nor more carefully (if `from`/`to`
      could be user input, or if the brace expansion could have spaces):\r\n\r\nfrom=\"a\"
      to=\"m\"\r\nwhile IFS= read -d '' -r c\r\ndo\r\n  echo \"Read $c\"\r\ndone <
      \ <(eval \"printf '%s\\0' $(printf \"{%q..%q}.jpg\" \"$from\" \"$to\")\")\r\n\r\n\r\n###
      Exceptions\r\n\r\nNone (if you're writing for e.g. zsh, make sure the shebang
      indicates this so shellcheck won't warn)\n\n\n### Notice\n\nOriginal content
      from the ShellCheck https://github.com/koalaman/shellcheck/wiki.\n"
SC2142:
  remediation_points: 50000
  content:
    body: |
      ## Aliases can't use positional parameters. Use a function.

      ### Problematic code:

      ```sh
      alias archive='mv "$@" /backup'
      ```

      ### Correct code:

      ```sh
      archive() { mv "$@" /backup; }

      ```

      ### Rationale:

      Aliases just substitute the start of a command with something else. They therefore can't use positional parameters, such as `$1`. Rewrite your alias as a function.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2072:
  remediation_points: 50000
  content:
    body: |
      ## Decimals are not supported. Either use integers only, or use bc or awk to compare.

      ### Problematic code:

      ```sh
      [[ 2 -lt 3.14 ]]
      ```

      ### Correct code:

      ```sh
      [[ 200 -lt 314 ]]                   # Use fixed point math
      [[ $(echo "2 < 3.14" | bc) == 1 ]]  # Use bc
      ```

      ### Rationale:

      Bash and Posix sh does not support decimals in numbers. Decimals should either be avoided, or compared using a tool that does support them.

      ### Exceptions

      If the strings happen to be version numbers and you're using `<`, or `>` to compare them as strings, and you consider this an acceptable thing to do, then you can ignore this warning.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1087:
  remediation_points: 50000
  content:
    body: |
      ## Braces are required when expanding arrays, as in ${array[idx]}.

      ### Problematic code:

      ```sh
      echo "$array[@]"
      ```

      ### Correct code:

      ```sh
      echo "${array[@]}"
      ```

      ### Rationale:

      For compatibility reasons, `$foo[bar]` is interpreted as the variable `$foo` followed by the literal string `[bar]`.

      Curly braces are needed to tell the shell that the square brackets are part of the expansion.

      ### Exceptions

      If you want the square brackets to be treated literally or as a glob, you can use `${var}[idx]` to prevent this warning.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2055:
  remediation_points: 50000
  content:
    body: |
      ## You probably wanted && here

      ### Problematic code:

      ```sh
      if [[ $1 != foo || $1 != bar ]]
      then
        echo "$1 is not foo or bar"
      fi
      ```

      ### Correct code:

      ```sh
      if [[ $1 != foo && $1 != bar ]]
      then
        echo "$1 is not foo or bar"
      fi
      ```

      ### Rationale:

      This is not a bash issue, but a simple, common logical mistake applicable to all languages.

      `[[ $1 != foo || $1 != bar ]]` is always true:

      * If `$1 = foo` then `$1 != bar` is true, so the statement is true.
      * If `$1 = bar` then `$1 != foo` is true, so the statement is true.
      * If `$1 = cow` then `$1 != foo` is true, so the statement is true.

      `[[ $1 != foo && $1 != bar ]]` matches when `$1` is not `foo` and not `bar`:

      * If `$1 = foo`, then `$1 != foo` is false, so the statement is false.
      * If `$1 = bar`, then `$1 != bar` is false, so the statement is false.
      * If `$1 = cow`, then both `$1 != foo` and `$1  != bar` is true, so the statement is true.

      This statement is identical to `! [[ $1 = foo || $1 = bar ]]`, which also works correctly.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2001:
  remediation_points: 50000
  content:
    body: |
      ## SC2001: See if you can use ${variable//search/replace} instead.

      ### Problematic code:

      ```sh
      string="stirng" ; echo "$string" | sed -e "s/ir/ri/"
      ```

      ### Correct code:

      ```sh
      string="stirng" ; echo "${string//ir/ri}"
      ```

      ### Rationale:

      Let's assume somewhere earlier in your code you have put data into a variable (Ex: $string). Now you want to do a search and replace inside the contents of $string and echo the contents out. You could pass this to sed as done in the example above, but for simple substitutions utilizing the shell for the same feature is a lot simpler and should be utilized whenever possible.

      ### Exceptions

      Occasionally a more complex sed substitution is required. For example, getting the last character of a string.

      ```sh
      string="stirng" ; echo "$string" | sed -e "s/^.*\(.\)$/\1/"
      ```

      This is a bit simple for the example and there are alternative ways of doing this in the shell, but this SC2001 flags on several of my crazy complex sed commands which are beyond the scope of this example. Utilizing some of the more complex capabilities of sed is required occasionally and it is safe to ignore SC2001.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1037:
  remediation_points: 50000
  content:
    body: |
      ## Braces are required for positionals over 9, e.g. ${10}.

      ### Problematic code:

      ```sh
      echo "Ninth parameter: $9"
      echo "Tenth parameter: $10"
      ```

      ### Correct code:

      ```sh
      echo "Ninth parameter: $9"
      echo "Tenth parameter: ${10}"
      ```

      ### Rationale:

      For legacy reasons, `$10` is interpreted as the variable `$1` followed by the literal string `0`.

      Curly braces are needed to tell the shell that both digits are part of the parameter expansion.

      ### Exceptions

      If you wanted the trailing digits to be literal, `${1}0` will make this clear to both humans and shellcheck.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2120:
  remediation_points: 50000
  content:
    body: |
      # foo references arguments, but none are ever passed.

      ### Problematic code:

      ```sh
      sayhello() {
        echo "Hello $1"
      }
      sayhello
      ```

      `./myscript World` just prints "Hello " instead of "Hello World".

      ### Correct code:

      ```sh
      sayhello() {
        echo "Hello $1"
      }
      sayhello "$@"
      ```

      `./myscript World` now prints "Hello World".

      ### Rationale:

      In a function, `$1` and up refers to the function's parameters, not the script's parameters.

      If you want to process your script's parameters in a function, you have to explicitly pass them. You can do this with `myfunction "$@"`.

      Note that `"$@"` refers to the current context's positional parameters, so if you call a function from a function, you have to pass in `"$@"` to both of them:

      ```sh
      first() { second "$@"; }
      second() { echo "The first script parameter is: $1"; }
      first "$@"
      ```

      ### Exceptions

      If the parameters are optional and you currently just don't want to use them, you can ignore this message.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2164:
  remediation_points: 50000
  content:
    body: |
      ## Use cd ... || exit in case cd fails.

      ### Problematic code:

      ```sh
      cd generated_files
      rm -r *.c
      ```

      ### Correct code:

      ```sh
      cd generated_files || exit
      rm -r *.c
      ```

      ### 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 direction. This can be messy, especially if the operations involve creating or deleting a lot of files.

      You should therefore always check the condition of `cd`, either with `|| exit` as suggested, or things like `if cd somewhere; then ...; fi`.

      ### 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.
SC2151:
  remediation_points: 50000
  content:
    body: |
      ## Only one integer 0-255 can be returned. Use stdout for other data.

      ### Problematic code:

      ```sh
      myfunc() {
        return foo bar
      }
      ```

      ### Correct code:

      ```sh
      myfunc() {
        echo foo
        echo bar
        return 0
      }
      ```

      ### Rationale:

      In bash, `return` can only be used to signal success or failure (0 = success, 1-255 = failure).

      To return textual or multiple values from a function, write them to stdout and capture them with command substitution instead.

      See [[SC2152]] for more information.

      ### Exceptions:

      None


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2028:
  remediation_points: 50000
  content:
    body: |
      # echo won't expand escape sequences. Consider printf.

      ### Problematic code:

      ```sh
      echo "Name:\t$value"
      ```

      ### Correct code:

      ```sh
      printf "Name:\t%s\n" "$value"
      ```

      ### Rationale:

      Backslash escapes like `\t` and `\n` are not expanded by echo, and become literal backslash-t, backslash-n.

      `printf` does expand these sequences, and should be used instead.

      Other, non-portable methods include `echo -e '\t'` and `echo $'\t'`. ShellCheck will warn if this is used in a script with shebang `#!/bin/sh`.

      If you actually wanted a literal backslash-t, use

      ```sh
      echo "\\t"
      ```

      ### Exceptions

      None


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2002:
  remediation_points: 50000
  content:
    body: |
      # Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead.

      ### Problematic code:

      ```sh
      cat file | tr ' ' _ | grep a_
      cat file | ( while read i; do echo "${i%?}"; done )
      ```

      ### Correct code:

      ```sh
      < file tr ' ' _ | grep a_  # **simple commands only, won't work with compounds
      ( while read i; do echo "${i%?}"; done ) < file # postfix works for everything
      ```

      ### Rationale:

      `cat` is a tool for con"cat"enating files. Reading a single file as input to a program is considered a [Useless Use Of Cat (UUOC)](http://en.wikipedia.org/wiki/Cat_(Unix)#Useless_use_of_cat).

      It's more efficient and less roundabout to simply use redirection. This is especially true for programs that can benefit from seekable input, like `tail` or `tar`.

      Many tools also accept optional filenames, e.g. `grep -q foo file` instead of `cat file | grep -q foo`.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1040:
  remediation_points: 50000
  content:
    body: |
      ## When using <<-, you can only indent with tabs.

      ### Problematic code:

      Any code using `<<-` that is indented with spaces. `cat -T script` shows

      ```sh
          cat <<- foo
              Hello world
          foo
      ```

      ### Correct code:

      Code using `<<-` must be indented with tabs. `cat -T script` shows

      ```sh
      ^Icat <<- foo
      ^I^IHello world
      ^Ifoo
      ```

      Or simply don't indent the end token:

      ```sh
          cat <<- foo
            Hello World
      foo
      ```

      ### Rationale:

      `<<-`, by design, only strips tabs. Not spaces.

      Your editor may be automatically replacing tabs with spaces, either when you type them or when you save the file or both. If you're unable to make it stop, just don't indent the end token.

      ### Exceptions

      None. But note that copy-pasting code to [shellcheck.net](http://www.shellcheck.net) may also turn correct tabs into spaces on some OS.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2060:
  remediation_points: 50000
  content:
    body: |
      # Quote parameters to tr to prevent glob expansion.

      ### Problematic code:

      ```sh
      tr -cd [:digit:]
      ```

      ### Correct code:

      ```sh
      tr -cd '[:digit:]'
      ```

      ### Rationale:

      `[:digit:]` is a shell glob that matches any single character file named e.g. `g` or `t` in the current directory. Quoting it prevents the script from breaking in directories with files like this.

      ### Exceptions

      None


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC1078:
  remediation_points: 50000
  content:
    body: |
      # Did you forget to close this double quoted string?

      ### Problematic code:

      ```sh
      greeting="hello
      target="world"
      ```

      ### Correct code:

      ```sh
      greeting="hello"
      target="world"
      ```

      ### Rationale:

      The first line is missing a quote.

      ShellCheck warns when it detects multi-line double quoted, single quoted or backticked strings when the character that follows it looks out of place (and gives a companion warning [[SC1079]] at that spot).

      ### Exceptions

      If you do want a multiline variable, just make sure the character after it is a quote, space or line feed.

      ```sh
      var='multiline
      'value
      ```

      can be rewritten for readability and to remove the warning:

      ```sh
      var='multiline
      value'
      ```

      As always `` `..` `` should be rewritten to ``$(..)``.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2030:
  remediation_points: 50000
  content:
    body: |
      # Modification of var is local (to subshell caused by pipeline).

      See companion warning [[SC2031]].


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2110:
  remediation_points: 50000
  content:
    body: |
      ## In [\[..]], use || instead of -o.

      ### Problematic code:

      ```sh
      [[ "$1" = "-v" -o "$1" = "-help" ]]
      ```

      ### Correct code:

      ```sh
      [[ "$1" = "-v" || "$1" = "-help" ]]
      ```

      ### Rationale:

      `-o` for logical OR is not supported in a `[[ .. ]]` expression. Use `||` instead.

      ### Exceptions:

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2039:
  remediation_points: 50000
  content:
    body: "## In POSIX sh, *something* is undefined.\nYou have declared that your
      script works with `/bin/sh`, but you are using features that have undefined
      behavior according to the POSIX specification. \n\nIt may currently work for
      you, but it can or will fail on other OS, the same OS with different configurations,
      from different contexts (like initramfs/chroot), or in different versions of
      the same OS, including future updates to your current system.\n\nEither declare
      that your script requires a specific shell like `#!/bin/bash` or `#!/bin/dash`,
      or rewrite the script in a portable way.\n\nFor help with rewrites, the Ubuntu
      wiki has [a list of portability issues](https://wiki.ubuntu.com/DashAsBinSh)
      that broke people's `#!/bin/sh` scripts when Ubuntu switched from Bash to Dash.
      ShellCheck may not warn about all these issues.\n\n### `$'c-style-escapes'`\n\nbash,
      ksh:\n\n```Bash\na=$' \\t\\n'\n```\n\nPOSIX:\n\n```sh\na=\"$(printf '%b_' '
      \\t\\n')\"; a=\"${a%_}\" # protect trailing \\n\n```\n\nWant some good news?
      See http://austingroupbugs.net/view.php?id=249#c590.\n\n### `$\"msgid\"`\n\nBash:\n\n```Bash\necho
      $\"foo $(bar) baz\"\n```\n\nPOSIX:\n\n```sh\n. gettext.sh # GNU Gettext sh library\n#
      ...\nbarout=$(bar)\neval_gettext 'foo $barout baz' # See GNU Gettext doc for
      more info.\n```\n\nOr you can change them to normal double quotes so you go
      without `gettext`.\n\n### Arithmetic `for` loops\n\nBash:\n\n```Bash\nfor ((init;
      test; next)); do foo; done\n```\n\nPOSIX:\n\n```sh\n: $((init))\nwhile [ $((test))
      -ne 0 ]; do foo; : $((next)); done\n```\n\n### standalone `((..))`\n\nBash:\n\n```Bash\n((a=c+d))\n((d))
      && echo d is true.\n```\n\nPOSIX:\n\n```sh\n: $((a=c+d)) # discard the output
      of the arith expn with `:` command\n[ $((d)) -ne 0 ] && echo d is true. # manually
      check non-zero => true\n```\n\n### `select` loops\n\nIt takes extra care over
      terminal columns to make select loop look like bash's, which generates a list
      with multiple items on one line, or like `ls`.\n\nIt is, however, still possible
      to make a naive translation for `select foo in bar baz; do eat; done`:\n\n```sh\nwhile\n
      \ _i=0 _foo= foo=\n  for _name in bar baz; do echo \"$((_i+=1))) $_name\"; done\n
      \ printf '$# '; read _foo\ndo\n  case _foo in 1) foo=bar;; 2) foo=baz;; *) continue;;
      esac\n  eat\ndone\n```\n\n### Here-strings\n\nBash, ksh:\n\n```Bash\ngrep aaa
      <<< \"$g\"\n```\n\nPOSIX:\n\n```sh\nprintf '%s' \"$g\" | grep aaa # since we
      want to avoid `echo`\n```\n\n### echo flags\n\nSee https://unix.stackexchange.com/tags/echo/info.\n\n###
      `${var/pat/replacement}`\n\nBash:\n\n```Bash\necho \"${TERM/%-256*}\"\n```\n\nPOSIX:\n\n```sh\necho
      \"$TERM\" | sed -e 's/-256.*$//g'\n# Special case for this since we are matching
      the end:\necho \"${TERM%-256*}\"\n```\n\n### `printf %q`\n\nBash:\n\n```Bash\nprintf
      '%q ' \"$@\"\n```\n\nPOSIX:\n\n```sh\n# TODO: Interpret it back to printf escapes
      for hard-to-copy chars like \\t?\n# See also: http://git.savannah.gnu.org/cgit/libtool.git/tree/gl/build-aux/funclib.sh?id=c60e054#n1029\nreuse_quote()(\n
      \ for i; do echo -n \\'; echo -n \"$i\" | sed -e \"s/'/'\\\\\\\\''/g\"; echo
      -n \"' \"; done\n)\nreuse_quote \"$@\"\n```\n\n## Exception\n\nDepends on what
      your expected POSIX shell providers would use.\n\n### Notice\n\nOriginal content
      from the ShellCheck https://github.com/koalaman/shellcheck/wiki.\n"
SC2025:
  remediation_points: 50000
  content:
    body: |
      # Make sure all escape sequences are enclosed in \[..\] to prevent line wrapping issues

      ### Problematic code:

      ```sh
      PS1='\e[36m\$ \e(B\e[m'
      ```

      ### Correct code:

      ```sh
      PS1='\[\e[36m\]\$ \[\e(B\e[m\]'
      ```

      ### Rationale:

      Bash is unable to determine exactly which parts of your prompt are text and which are terminal codes. You have to help it by wrapping invisible control codes in `\[..\]` (and ensuring that visible characters are not wrapped in `\[..\]`).

      Note: ShellCheck offers this as a helpful hint and not a robust check. Don't rely on ShellCheck to verify that your prompt is correct.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2152:
  remediation_points: 50000
  content:
    body: |
      ## Can only return 0-255. Other data should be written to stdout.

      ### Problematic code:

      ```sh
      myfunc() {
        return "Hello $USER"
      }
      ```

      ### Correct code:

      ```sh
      myfunc() {
        echo "Hello $USER"
        return 0
      }
      ```

      ### Rationale:

      In many languages, `return` is used to return from the function with a final result.

      In bash, `return` can only be used to signal success or failure (0 = success, 1-255 = failure), more akin to `throw/raise` in other languages.

      Results should instead be written to stdout and captured:

      ```sh
      message=$(myfunc)
      echo "The function wrote: $message"
      ```

      In functions that return small integers, such as getting the cpu temperature, the value should still be written to stdout. `return` should be reserved for error conditions, such as "can't determine CPU temperature".

      ### Exceptions:

      None


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2101:
  remediation_points: 50000
  content:
    body: |
      # Named class needs outer [], e.g. [[:digit:]\].

      ### Problematic code:

      ```sh
      gzip file[:digit:]*.txt
      ```

      ### Correct code:

      ```sh
      gzip file[[:digit:]]*.txt
      ```

      ### Rationale:

      Predefined character groups are supposed to be used inside character ranges. `[:digit:]` matches one of "digt:" just like `[abc]` matches one of "abc". `[[:digit:]]` matches a digit.

      ### Exceptions

      When passing an argument to `tr` which parses these by itself without relying on globbing, you should quote it instead, e.g. `tr -d '[:digit:]'`


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2117:
  remediation_points: 50000
  content:
    body: |
      ## To run commands as another user, use su -c or sudo.

      ### Problematic code:

      ```sh
      whoami
      su
      whoami
      ```

      ### Correct code:

      ```sh
      whoami
      sudo whoami
      ```

      ### Rationale:

      It's commonly believed that `su` makes a session run as another user. In reality, it starts an entirely new shell, independent of the one currently running your script.

      `su; whoami` will start a root shell and wait for it to exit before running `whoami`. It will not start a root shell and then proceed to run `whoami` in it.

      To run commands as another user, use `sudo some command` or `su -c 'some command'`. `sudo` is preferred when available, as it doesn't require additional quoting and can be configured to run passwordless if desired.


      ### Exceptions

      If you're aware of the above and want to e.g. start an interactive shell for a user, feel free to ignore this message.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.
SC2124:
  remediation_points: 50000
  content:
    body: |
      ## Assigning an array to a string! Assign as array, or use * instead of @ to concatenate.

      ### Problematic code:

      ```sh
      var=$@
      for i in $var; do ..; done
      ```

      or

      ```sh
      set -- Hello World
      msg=$@
      echo "You said $msg"
      ```

      ### Correct code:

      ```sh
      var=( "$@" )
      for i in "${var[@]}"; do ..; done
      ```

      or

      ```sh
      set -- Hello World
      msg=$*
      echo "You said $msg"
      ```

      ### Rationale:

      Arrays and `$@` can contain multiple elements. Simple variables contain only one. When assigning multiple elements to one element, the default behavior depends on the shell (bash concatenates with spaces, zsh concatenates with first char of `IFS`).

      Since doing this usually indicates a bug, ShellCheck warns and asks you to be explicit about what you want.

      If you want to assign N elements as N elements, use an array, e.g. `myArray=( "$@" )`.

      If you want to assign N elements as 1 element by concatenating them, use `*` instead of `@`, e.g. `myVar=${myArray[*]}` (this separates elements with the first character of `IFS`, usually space).

      The same is true for `${@: -1}`, which results in 0 or 1 elements: `var=${*: -1}` assigns the last element or an empty string.

      ### Exceptions

      None.


      ### Notice

      Original content from the ShellCheck https://github.com/koalaman/shellcheck/wiki.