Shellcheck - a static analysis tool for shell scripts

Overview

Build Status

ShellCheck - A shell script static analysis tool

ShellCheck is a GPLv3 tool that gives warnings and suggestions for bash/sh shell scripts:

Screenshot of a terminal showing problematic shell script lines highlighted

The goals of ShellCheck are

  • To point out and clarify typical beginner's syntax issues that cause a shell to give cryptic error messages.

  • To point out and clarify typical intermediate level semantic problems that cause a shell to behave strangely and counter-intuitively.

  • To point out subtle caveats, corner cases and pitfalls that may cause an advanced user's otherwise working script to fail under future circumstances.

See the gallery of bad code for examples of what ShellCheck can help you identify!

Table of Contents

How to use

There are a number of ways to use ShellCheck!

On the web

Paste a shell script on https://www.shellcheck.net for instant feedback.

ShellCheck.net is always synchronized to the latest git commit, and is the easiest way to give ShellCheck a go. Tell your friends!

From your terminal

Run shellcheck yourscript in your terminal for instant output, as seen above.

In your editor

You can see ShellCheck suggestions directly in a variety of editors.

Screenshot of Vim showing inlined shellcheck feedback.

Screenshot of emacs showing inlined shellcheck feedback.

In your build or test suites

While ShellCheck is mostly intended for interactive use, it can easily be added to builds or test suites. It makes canonical use of exit codes, so you can just add a shellcheck command as part of the process.

For example, in a Makefile:

check-scripts:
    # Fail if any of these files have warnings
    shellcheck myscripts/*.sh

or in a Travis CI .travis.yml file:

script:
  # Fail if any of these files have warnings
  - shellcheck myscripts/*.sh

Services and platforms that have ShellCheck pre-installed and ready to use:

Most other services, including GitLab, let you install ShellCheck yourself, either through the system's package manager (see Installing), or by downloading and unpacking a binary release.

It's a good idea to manually install a specific ShellCheck version regardless. This avoids any surprise build breaks when a new version with new warnings is published.

For customized filtering or reporting, ShellCheck can output simple JSON, CheckStyle compatible XML, GCC compatible warnings as well as human readable text (with or without ANSI colors). See the Integration wiki page for more documentation.

Installing

The easiest way to install ShellCheck locally is through your package manager.

On systems with Cabal (installs to ~/.cabal/bin):

cabal update
cabal install ShellCheck

On systems with Stack (installs to ~/.local/bin):

stack update
stack install ShellCheck

On Debian based distros:

sudo apt install shellcheck

On Arch Linux based distros:

pacman -S shellcheck

or get the dependency free shellcheck-bin from the AUR.

On Gentoo based distros:

emerge --ask shellcheck

On EPEL based distros:

sudo yum -y install epel-release
sudo yum install ShellCheck

On Fedora based distros:

dnf install ShellCheck

On FreeBSD:

pkg install hs-ShellCheck

On macOS (OS X) with Homebrew:

brew install shellcheck

Or with MacPorts:

sudo port install shellcheck

On OpenBSD:

pkg_add shellcheck

On openSUSE

zypper in ShellCheck

Or use OneClickInstall - https://software.opensuse.org/package/ShellCheck

On Solus:

eopkg install shellcheck

On Windows (via chocolatey):

C:\> choco install shellcheck

Or Windows (via scoop):

C:\> scoop install shellcheck

From conda-forge:

conda install -c conda-forge shellcheck

From Snap Store:

snap install --channel=edge shellcheck

From Docker Hub:

docker run --rm -v "$PWD:/mnt" koalaman/shellcheck:stable myscript
# Or :v0.4.7 for that version, or :latest for daily builds

or use koalaman/shellcheck-alpine if you want a larger Alpine Linux based image to extend. It works exactly like a regular Alpine image, but has shellcheck preinstalled.

Using the nix package manager:

nix-env -iA nixpkgs.shellcheck

Alternatively, you can download pre-compiled binaries for the latest release here:

or see the GitHub Releases for other releases (including the latest meta-release for daily git builds).

Distro packages already come with a man page. If you are building from source, it can be installed with:

pandoc -s -f markdown-smart -t man shellcheck.1.md -o shellcheck.1
sudo mv shellcheck.1 /usr/share/man/man1

pre-commit

To run ShellCheck via pre-commit, add the hook to your .pre-commit-config.yaml:

repos:
-   repo: https://github.com/koalaman/shellcheck-precommit
    rev: v0.7.2
    hooks:
    -   id: shellcheck
#       args: ["--severity=warning"]  # Optionally only show errors and warnings

Travis CI

Travis CI has now integrated ShellCheck by default, so you don't need to manually install it.

If you still want to do so in order to upgrade at your leisure or ensure you're using the latest release, follow the steps below to install a binary version.

Installing a pre-compiled binary

The pre-compiled binaries come in tar.xz files. To decompress them, make sure xz is installed. On Debian/Ubuntu/Mint, you can apt install xz-utils. On Redhat/Fedora/CentOS, yum -y install xz.

A simple installer may do something like:

scversion="stable" # or "v0.4.7", or "latest"
wget -qO- "https://github.com/koalaman/shellcheck/releases/download/${scversion?}/shellcheck-${scversion?}.linux.x86_64.tar.xz" | tar -xJv
cp "shellcheck-${scversion}/shellcheck" /usr/bin/
shellcheck --version

Compiling from source

This section describes how to build ShellCheck from a source directory. ShellCheck is written in Haskell and requires 2GB of RAM to compile.

Installing Cabal

ShellCheck is built and packaged using Cabal. Install the package cabal-install from your system's package manager (with e.g. apt-get, brew, emerge, yum, or zypper).

On macOS (OS X), you can do a fast install of Cabal using brew, which takes a couple of minutes instead of more than 30 minutes if you try to compile it from source.

$ brew install cabal-install

On MacPorts, the package is instead called hs-cabal-install, while native Windows users should install the latest version of the Haskell platform from https://www.haskell.org/platform/

Verify that cabal is installed and update its dependency list with

$ cabal update

Compiling ShellCheck

git clone this repository, and cd to the ShellCheck source directory to build/install:

$ cabal install

Or if you intend to run the tests:

$ cabal install --enable-tests

This will compile ShellCheck and install it to your ~/.cabal/bin directory.

Add this directory to your PATH (for bash, add this to your ~/.bashrc):

export PATH="$HOME/.cabal/bin:$PATH"

Log out and in again, and verify that your PATH is set up correctly:

$ which shellcheck
~/.cabal/bin/shellcheck

On native Windows, the PATH should already be set up, but the system may use a legacy codepage. In cmd.exe, powershell.exe and Powershell ISE, make sure to use a TrueType font, not a Raster font, and set the active codepage to UTF-8 (65001) with chcp:

chcp 65001

In Powershell ISE, you may need to additionally update the output encoding:

[Console]::OutputEncoding = [System.Text.Encoding]::UTF8

Running tests

To run the unit test suite:

$ cabal test

Gallery of bad code

So what kind of things does ShellCheck look for? Here is an incomplete list of detected issues.

Quoting

ShellCheck can recognize several types of incorrect quoting:

echo $1                           # Unquoted variables
find . -name *.ogg                # Unquoted find/grep patterns
rm "~/my file.txt"                # Quoted tilde expansion
v='--verbose="true"'; cmd $v      # Literal quotes in variables
for f in "*.ogg"                  # Incorrectly quoted 'for' loops
touch $@                          # Unquoted $@
echo 'Don't forget to restart!'   # Singlequote closed by apostrophe
echo 'Don\'t try this at home'    # Attempting to escape ' in ''
echo 'Path is $PATH'              # Variables in single quotes
trap "echo Took ${SECONDS}s" 0    # Prematurely expanded trap
unset var[i]                      # Array index treated as glob

Conditionals

ShellCheck can recognize many types of incorrect test statements.

[[ n != 0 ]]                      # Constant test expressions
[[ -e *.mpg ]]                    # Existence checks of globs
[[ $foo==0 ]]                     # Always true due to missing spaces
[[ -n "$foo " ]]                  # Always true due to literals
[[ $foo =~ "fo+" ]]               # Quoted regex in =~
[ foo =~ re ]                     # Unsupported [ ] operators
[ $1 -eq "shellcheck" ]           # Numerical comparison of strings
[ $n && $m ]                      # && in [ .. ]
[ grep -q foo file ]              # Command without $(..)
[[ "$$file" == *.jpg ]]           # Comparisons that can't succeed
(( 1 -lt 2 ))                     # Using test operators in ((..))
[ x ] & [ y ] | [ z ]             # Accidental backgrounding and piping

Frequently misused commands

ShellCheck can recognize instances where commands are used incorrectly:

bar \; # Redirections in find f() { whoami; }; sudo f # External use of internal functions ">
grep '*foo*' file                 # Globs in regex contexts
find . -exec foo {} && bar {} \;  # Prematurely terminated find -exec
sudo echo 'Var=42' > /etc/profile # Redirecting sudo
time --format=%s sleep 10         # Passing time(1) flags to time builtin
while read h; do ssh "$h" uptime  # Commands eating while loop input
alias archive='mv $1 /backup'     # Defining aliases with arguments
tr -cd '[a-zA-Z0-9]'              # [] around ranges in tr
exec foo; echo "Done!"            # Misused 'exec'
find -name \*.bak -o -name \*~ -delete  # Implicit precedence in find
# find . -exec foo > bar \;       # Redirections in find
f() { whoami; }; sudo f           # External use of internal functions

Common beginner's mistakes

ShellCheck recognizes many common beginner's syntax errors:

var = 42                          # Spaces around = in assignments
$foo=42                           # $ in assignments
for $var in *; do ...             # $ in for loop variables
var$n="Hello"                     # Wrong indirect assignment
echo ${var$n}                     # Wrong indirect reference
var=(1, 2, 3)                     # Comma separated arrays
array=( [index] = value )         # Incorrect index initialization
echo $var[14]                     # Missing {} in array references
echo "Argument 10 is $10"         # Positional parameter misreference
if $(myfunction); then ..; fi     # Wrapping commands in $()
else if othercondition; then ..   # Using 'else if'
f; f() { echo "hello world; }     # Using function before definition
[ false ]                         # 'false' being true
if ( -f file )                    # Using (..) instead of test

Style

ShellCheck can make suggestions to improve style:

[[ -z $(find /tmp | grep mpg) ]]  # Use grep -q instead
a >> log; b >> log; c >> log      # Use a redirection block instead
echo "The time is `date`"         # Use $() instead
cd dir; process *; cd ..;         # Use subshells instead
echo $[1+2]                       # Use standard $((..)) instead of old $[]
echo $(($RANDOM % 6))             # Don't use $ on variables in $((..))
echo "$(date)"                    # Useless use of echo
cat file | grep foo               # Useless use of cat

Data and typing errors

ShellCheck can recognize issues related to data and typing:

2 ]] # Comparing numbers as strings var=World; echo "Hello " var # Unused lowercase variables echo "Hello $name" # Unassigned lowercase variables cmd | read bar; echo $bar # Assignments in subshells cat foo | cp bar # Piping to commands that don't read printf '%s: %s\n' foo # Mismatches in printf argument count eval "${array[@]}" # Lost word boundaries in array eval for i in "${x[@]}"; do ${x[$i]} # Using array value as key ">
args="$@"                         # Assigning arrays to strings
files=(foo bar); echo "$files"    # Referencing arrays as strings
declare -A arr=(foo bar)          # Associative arrays without index
printf "%s\n" "Arguments: $@."    # Concatenating strings and arrays
[[ $# > 2 ]]                      # Comparing numbers as strings
var=World; echo "Hello " var      # Unused lowercase variables
echo "Hello $name"                # Unassigned lowercase variables
cmd | read bar; echo $bar         # Assignments in subshells
cat foo | cp bar                  # Piping to commands that don't read
printf '%s: %s\n' foo             # Mismatches in printf argument count
eval "${array[@]}"                # Lost word boundaries in array eval
for i in "${x[@]}"; do ${x[$i]}   # Using array value as key

Robustness

ShellCheck can make suggestions for improving the robustness of a script:

rm -rf "$STEAMROOT/"*            # Catastrophic rm
touch ./-l; ls *                 # Globs that could become options
find . -exec sh -c 'a && b {}' \; # Find -exec shell injection
printf "Hello $name"             # Variables in printf format
for f in $(ls *.txt); do         # Iterating over ls output
export MYVAR=$(cmd)              # Masked exit codes
case $version in 2.*) :;; 2.6.*) # Shadowed case branches

Portability

ShellCheck will warn when using features not supported by the shebang. For example, if you set the shebang to #!/bin/sh, ShellCheck will warn about portability issues similar to checkbashisms:

echo {1..$n}                     # Works in ksh, but not bash/dash/sh
echo {1..10}                     # Works in ksh and bash, but not dash/sh
echo -n 42                       # Works in ksh, bash and dash, undefined in sh
expr match str regex             # Unportable alias for `expr str : regex`
trap 'exit 42' sigint            # Unportable signal spec
cmd &> file                      # Unportable redirection operator
read foo < /dev/tcp/host/22      # Unportable intercepted files
foo-bar() { ..; }                # Undefined/unsupported function name
[ $UID = 0 ]                     # Variable undefined in dash/sh
local var=value                  # local is undefined in sh
time sleep 1 | sleep 5           # Undefined uses of 'time'

Miscellaneous

ShellCheck recognizes a menagerie of other issues:

file # Redirecting to input var2=$var2 # Variable assigned to itself [ x$var = xval ] # Antiquated x-comparisons ls() { ls -l "$@"; } # Infinitely recursive wrapper alias ls='ls -l'; ls foo # Alias used before it takes effect for x; do for x; do # Nested loop uses same variable while getopts "a" f; do case $f in "b") # Unhandled getopts flags ">
PS1='\e[0;32m\$\e[0m '            # PS1 colors not in \[..\]
PATH="$PATH:~/bin"                # Literal tilde in $PATH
rm “file”                         # Unicode quotes
echo "Hello world"                # Carriage return / DOS line endings
echo hello \                      # Trailing spaces after \
var=42 echo $var                  # Expansion of inlined environment
!# bin/bash -x -e                 # Common shebang errors
echo $((n/180*100))               # Unnecessary loss of precision
ls *[:digit:].txt                 # Bad character class globs
sed 's/foo/bar/' file > file      # Redirecting to input
var2=$var2                        # Variable assigned to itself
[ x$var = xval ]                  # Antiquated x-comparisons
ls() { ls -l "$@"; }              # Infinitely recursive wrapper
alias ls='ls -l'; ls foo          # Alias used before it takes effect
for x; do for x; do               # Nested loop uses same variable
while getopts "a" f; do case $f in "b") # Unhandled getopts flags

Testimonials

At first you're like "shellcheck is awesome" but then you're like "wtf are we still using bash"

Alexander Tarasikov, via Twitter

Ignoring issues

Issues can be ignored via environmental variable, command line, individually or globally within a file:

https://github.com/koalaman/shellcheck/wiki/Ignore

Reporting bugs

Please use the GitHub issue tracker for any bugs or feature suggestions:

https://github.com/koalaman/shellcheck/issues

Contributing

Please submit patches to code or documentation as GitHub pull requests! Check out the DevGuide on the ShellCheck Wiki.

Contributions must be licensed under the GNU GPLv3. The contributor retains the copyright.

Copyright

ShellCheck is licensed under the GNU General Public License, v3. A copy of this license is included in the file LICENSE.

Copyright 2012-2019, Vidar 'koala_man' Holen and contributors.

Happy ShellChecking!

Other Resources

  • The wiki has long form descriptions for each warning, e.g. SC2221.
  • ShellCheck does not attempt to enforce any kind of formatting or indenting style, so also check out shfmt!
Comments
  • False positive SC2030/SC2031 in 0.7.2?

    False positive SC2030/SC2031 in 0.7.2?

    For bugs

    • Rule Id (if any, e.g. SC1000): SC2030/SC2031
    • My shellcheck version (shellcheck --version or "online"): 0.7.2
    • [x] The rule's wiki page does not already cover this (e.g. https://shellcheck.net/wiki/SC2031)
    • [x] I tried on https://www.shellcheck.net/ and verified that this is still a problem on the latest commit

    Here's a snippet or screenshot that shows the problem:

    
    #!/bin/bash
    
    test1() {
         echo "Test" | if [[ -n "$LOGFILE" ]]; then tee -a "$LOGFILE"; else cat; fi
    }
    
    test2() {
            echo "ERROR" | tee -a "$LOGFILE"
    }
    

    Here's what shellcheck currently says:

    $ shellcheck myscript
     
    Line 4:
         echo "Test" | if [[ -n "$LOGFILE" ]]; then tee -a "$LOGFILE"; else cat; fi
                                 ^-- SC2030: Modification of LOGFILE is local (to subshell caused by pipeline).
     
    Line 8:
            echo "ERROR" | tee -a "$LOGFILE"
                                   ^-- SC2031: LOGFILE was modified in a subshell. That change might be lost.
    
    
    

    Here's what I wanted or expected to see:

    Nothing as in 0.7.1 shellcheck.

    Everything was ok before last update. Can you check please?

    opened by Stikus 41
  • Use file extension to detect shell

    Use file extension to detect shell

    • Rule Id 2148
    • My shellcheck version 0.5.0:
    • [x] I read the issue's wiki page, e.g. https://github.com/koalaman/shellcheck/wiki/SC2148
    • [x] I searched through https://github.com/koalaman/shellcheck/issues and didn't find anything related

    Why doesn't shellcheck consider the file extension to decide which shell is in play? I couldn't find any issues related to this. I write a lot of bash libraries that have a .bash file extension. I don't have a good reason for a shebang in those files.

    opened by ingydotnet 34
  • SC2230 - command -v is not a direct replacement for which

    SC2230 - command -v is not a direct replacement for which

    For bugs

    • Rule Id (if any, e.g. SC1000): SC2230
    • My shellcheck version (shellcheck --version or "online"): 4.4.7 (latest from git)
    • [X] I tried on shellcheck.net and verified that this is still a problem on the latest commit

    Here's a snippet or screenshot that shows the problem:

    
    #!/bin/sh
    
    which "$0"
    /usr/bin/which "$0"
    command -v "$0"
    
    

    Here's what shellcheck currently says:

    In test.sh line 3: which "$0" ^-- SC2230: which is non-standard. Use builtin 'command -v' instead.

    In test.sh line 4: /usr/bin/which "$0" ^-- SC2230: which is non-standard. Use builtin 'command -v' instead.

    Here's what I wanted or expected to see:

    Because "command -v" does not do the same as which, I would have liked to see nothing. When running the above (from /tmp), I get: /tmp/test.sh /tmp/test.sh ./test.sh

    While "which" may not be standard, it is commonly used to get the full path. At the very least I would like to not get warned when I specifically use the path as in the third command - then it's fairly certain what the user wants, which won't be the common bash alias.

    opened by arth1 28
  • SC1090/SC1091: sourcing should find files relative to script

    SC1090/SC1091: sourcing should find files relative to script

    When using the directive source=foobar.sh, then it seems to look up the source relative to the path shellcheck is being run from. For example, I have the following scripts: foo.sh and foobar.sh in the same directory (for example bar/baz from the project root).

    Suppose there is the following line in foo.sh:

    source "${0%/*}/foobar.sh"
    

    I will get a SC1090 error because shellcheck is unable to resolve the path. I have to do this:

    # shellcheck source bar/baz/foobar.sh
    source "${0%/*}/foobar.sh"
    

    This works, but only if I run the checker from the project root (either by specifying foo/bar/foobar.sh as an input file, or with -x), but not if I run it from anywhere else. There should be a way to tell shellcheck to look for a file relative to the checked file's location, not where shellcheck is run. For example, this way:

    # shellcheck source ./foobar.sh
    source "${0%/*}/foobar.sh"
    
    opened by petersohn 25
  • SC2181 suggests to check exit code directly when I check for several possible values

    SC2181 suggests to check exit code directly when I check for several possible values

    • Rule Id: SC2181
    • My shellcheck version: 0.4.7
    • [x] I tried on shellcheck.net and verified that this is still a problem on the latest commit
    • [ ] It's not reproducible on shellcheck.net, but I think that's because it's an OS, configuration or encoding issue

    Here's a snippet that shows the problem:

    
    #!/usr/bin/env bash
    
    gzip --test "$1"
    if [[ $? -eq 0 || $? -eq 2 ]]
    then
        echo ok
    else
        echo bad
    fi
    

    Here's what shellcheck currently says:

    In shellcheck-issue.sh line 4: if [[ $? -eq 0 || $? -eq 2 ]] ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

    Here's what I wanted or expected to see:

    Nothing, because the successful operation is not the only exit code I'm testing against. gzip possible exit statuses:

    Exit status is normally 0; if an error occurs, exit status is 1. If a warning occurs, exit status is 2.
    

    I want to test for both normal and warning, i.e. any of 0 and 2. And the remaining exit status - 1 falls into the else conditional path.

    Moreover, shellcheck is silent for

    if $? || [[ $? -eq 2 ]]
    

    that is completely wrong. Since testing the first expression $? actually gets executed and rewrites the gzip exit code value. So that the second [[ $? -eq 2 ]] never matches.

    P.S. Of course, I could test just for exit status 1 in my case, but there could be new exit statues beside 0, 1, 2 in general.

    opened by AleXoundOS 21
  • shellcheck: unable to decommit memory: Invalid argument (0.4.4)

    shellcheck: unable to decommit memory: Invalid argument (0.4.4)

    Howdy,

    I recently upgraded my project to using shellcheck 0.4.4 on travis-ci.org to take advantage of the new global file exclusions (#777). After doing so, shellcheck is throwing lots of errors on my project, with the message: +shellcheck -s sh src/winetricks shellcheck: unable to decommit memory: Invalid argument shellcheck: unable to decommit memory: Invalid argument shellcheck: unable to decommit memory: Invalid argument shellcheck: unable to decommit memory: Invalid argument shellcheck: unable to decommit memory: Invalid argument shellcheck: unable to decommit memory: Invalid argument shellcheck: unable to decommit memory: Invalid argument shellcheck: unable to decommit memory: Invalid argument shellcheck: unable to decommit memory: Invalid argument

    What's interesting is that it only occurs on Linux (Ubuntu): https://travis-ci.org/Winetricks/winetricks/jobs/177866938

    But not OS X with 0.4.5: https://travis-ci.org/Winetricks/winetricks/jobs/177866939

    is this a known issue with 0.4.4? I glanced through the commits between 0.4.4 and 0.4.5, but didn't see anything relevant. Unfortunately, Ubuntu's latest is 0.4.4: https://launchpad.net/ubuntu/+source/shellcheck

    so if it is fixed in 0.4.5, I'd like to know so I can ask Ubuntu to bump it.

    P.S., I hate filing a bug for this since it's a previous version, but I couldn't find an IRC channel to ask about this. Is there one I'm unaware of?

    opened by austin987 20
  • install error 0.4.2

    install error 0.4.2

    I tried to install 0.4.2 on my Ubuntu 14.04.3 x64 and got following errors, any thought what seem to be the issue?

    In-place registering QuickCheck-2.8.1...
    Installing library in /root/.cabal/lib/QuickCheck-2.8.1/ghc-7.6.3
    Registering QuickCheck-2.8.1...
    Installed QuickCheck-2.8.1
    Downloading ShellCheck-0.4.2...
    [1 of 1] Compiling Main             ( /tmp/ShellCheck-0.4.2-23628/ShellCheck-0.4.2/Setup.hs, /tmp/ShellCheck-0.4.2-23628/ShellCheck-0.4.2/dist/setup/Main.o )
    
    /tmp/ShellCheck-0.4.2-23628/ShellCheck-0.4.2/Setup.hs:15:25:
        Module `System.Process' does not export `callCommand'
    Failed to install ShellCheck-0.4.2
    cabal: Error: some packages failed to install:
    ShellCheck-0.4.2 failed during the configure step. The exception was:
    ExitFailure 1
    
    opened by gdbtek 20
  • Add new check for error ignoring on command substitutions

    Add new check for error ignoring on command substitutions

    For new checks and feature suggestions

    • [x] https://www.shellcheck.net/ (i.e. the latest commit) currently gives no useful warnings about this
    • [x] I searched through https://github.com/koalaman/shellcheck/issues and didn't find anything related

    Suggestion

    Given the following script:

    #!/bin/bash
    
    set -e
    
    basename "$(curl -fsSL -w '%{url_effective}' -o /dev/null https://github.com/docker/compose/releases/latest)"
    

    It would normally work, but curl could actually fail (such as with command not found). So, for the sake of the example, I will force it to fail by using curl2.

    Examples:

    $ bash <<'EOF'; echo $?
    #!/bin/bash
    
    set -e
    
    basename "$(curl -fsSL -w '%{url_effective}' -o /dev/null https://github.com/docker/compose/releases/latest)"
    EOF
    v2.0.0
    0
    

    With curl2:

    $ bash <<'EOF'; echo $?
    #!/bin/bash
    
    set -e
    
    basename "$(curl2 -fsSL -w '%{url_effective}' -o /dev/null https://github.com/docker/compose/releases/latest)"
    EOF
    bash: line 5: curl2: command not found
    
    0
    

    The status code of the latter example is 0 even if the command failed. This is misleading. ShellCheck could advise to be written like so instead:

    $ bash <<'EOF'; echo $?
    #!/bin/bash
    
    set -e
    
    curl_output="$(curl2 -fsSL -w '%{url_effective}' -o /dev/null https://github.com/docker/compose/releases/latest)"
    basename "$curl_output"
    EOF
    bash: line 5: curl2: command not found
    127
    

    References https://github.com/twpayne/chezmoi/issues/1466#issuecomment-929709757

    opened by felipecrs 18
  • [Feature] Auto Fix

    [Feature] Auto Fix

    I searched issues for "auto fix" and didn't find anything related. Is there any interest in an auto fix feature?

    When first discovering shellcheck, and when inheriting code, and when upgrading to a new version of shellcheck there can be an overwhelming number of simple fixes that can be solved by find . -iname '*.sh' | xargs -I {} perl -pi -e "$RE" {} followed by git diff-highlight review of course. So instead of everyone independently creating $RE we could have an "auto fix" feature that would make a best effort to correct common issues.

    Am I the outlier here or is anyone else accumulating a list of Regular Expressions to help fix issues identified by shellcheck?

    autofix 
    opened by Dmole 18
  • Feature request: Force bash style ( [[ ... ]] ) testing

    Feature request: Force bash style ( [[ ... ]] ) testing

    For new checks and feature suggestions

    • [x] shellcheck.net (i.e. the latest commit) currently gives no useful warnings about this
    • [x] I searched through https://github.com/koalaman/shellcheck/issues and didn't find anything related

    Here's a snippet or screenshot that shows the problem:

    #!/bin/bash
    if [ "$1" == 'b' ]; then
        echo 1
    fi
    

    Here's what shellcheck currently says:

    No issues detected!

    Here's what I wanted or expected to see:

    Warning: use bash style ( [[ ... ]] ) testing for better performance

    opened by andras-tim 18
  • Regarding shell scripts that are only meant to be source (SC2148)

    Regarding shell scripts that are only meant to be source (SC2148)

    Shellcheck looks to the shebang statement at the beginning of a shell script as one means of determining what language is used. This works well for shell scripts that are meant to be called as an executable.

    However, there are non-executable shell files where the convention is to not include the shebang statement in the file because they are meant to be sourced either by the shell during startup (e.g., bashrc) or because they are part of a shell library.

    These files would benefit from spellcheck but can't be used as they are without including a shebang statement.

    I'd like to propose a directive for this specific case that can specify the language. Something like:

    # shellcheck lang=bash
    

    There are other related issues that have brought up this issue but the suggestions were to fall back to sh #215 or ignore the issue #237. I think it'd be best to allow your users the ability to specify the language type to take advantage of language specific features.

    I recognize that shellcheck -s dialect exists but this doesn't help in the case of vim's syntastic plugin.

    Finally, the lang directive should throw a warning if a shebang is used simultaneously.

    Alternatively, the shebang statement could simply be added to these files but I hesitate here because this is not the convention for source files.

    Thoughts?

    opened by chauncey-garrett 18
  • Warn when using deprecated rgrep

    Warn when using deprecated rgrep

    Just as egrep and fgrep have been deprecated by both the POSIX and GNU versions of grep, Debian has deprecated the rgrep command it injects into the GNU grep package they distribute. (Which Ubuntu inherits, as well.)

    The patches applied by Debian now list all three as deprecated (though all three are also listed as "Debian-specific", so perhaps egrep and fgrep have already been removed upstream?), even though it also removes the deprecation warning from egrep and fgrep (rgrep never had one).

    This PR adds a new rule, SC2324, which is identical to SC2196 and SC2197 save that it targets rgrep. As a bonus, rgrep has also been added to the list of greps for which -q should be suggested (SC2143).

    It probably also makes sense to add all three variants to SC2126 (piping grep to wc -l when grep -c could be used instead), but I didn't discover that until I was typing up this description and my (fairly limited) Haskell skills aren't up to doing it quickly. 😅 If others agree that it should be done though, I'll happily make the change when I have more time in the next few days.

    opened by benblank 0
  • CLI argument documentation isn't available online?

    CLI argument documentation isn't available online?

    It's possible that my search-fu has simply failed me, but I wasn't able to find documentation equivalent to shellcheck --help (i.e. descriptions of the various command-line arguments) online. I checked the README, the GitHub wiki, and shellcheck.net, but wasn't able to turn anything up. (For that matter, I didn't see a dedicated description of .shellcheckrc and how to use it, either.)

    Even just piping the output of shellcheck --help to a file (or rendering the man page as HTML) and making it available on (preferably) both the GitHub wiki and shellcheck.net would be a real help!

    opened by benblank 0
  • Potential false positive SC2320

    Potential false positive SC2320

    For bugs

    • Rule Id (if any, e.g. SC1000): SC2320
    • My shellcheck version (shellcheck --version or "online"): 0.9.0
    • [ X] The rule's wiki page does not already cover this (e.g. https://shellcheck.net/wiki/SC2086)
    • [ X] I tried on https://www.shellcheck.net/ and verified that this is still a problem on the latest commit

    For new checks and feature suggestions

    • [ X] https://www.shellcheck.net/ (i.e. the latest commit) currently gives no useful warnings about this
    • [ X] I searched through https://github.com/koalaman/shellcheck/issues and didn't find anything related

    Here's a snippet or screenshot that shows the problem:

    
    #!/bin/bash
    echo "some print that can fail" || exit $?
    
    

    Here's what shellcheck currently says:

    ^-- SC2320 (warning): This $? refers to echo/printf, not a previous command. Assign to variable to avoid it being overwritten.

    Here's what I wanted or expected to see:

    I might be wrong, but I would assume that this shouldn't trigger a warning as the $? isn't part of the print command itself, and is expected to get the return code from the print statement. The || exit is meant to trigger if something goes wrong on the same line, therefore the return code in $? refers to the correct line.

    I use this format in almost all of my shell scripts, I don't want to ignore the warning as it should trigger in cases like the one mentioned in the wiki, so I'm wondering if this is expected behavior or if this is a bug that should be fixed so I can know if I need to change all my shell scripts or if this is accepted behavior in a later release. I haven't seen this warning before yesterday where I updated from shellcheck 0.8.0 to 0.9.0

    opened by Martiix 1
  • Another false positive for SC2050 when compared with

    Another false positive for SC2050 when compared with ""

    For bugs

    • Rule Id (if any, e.g. SC1000): SC2050
    • My shellcheck version (shellcheck --version or "online"): online
    • [X] The rule's wiki page does not already cover this (e.g. https://shellcheck.net/wiki/SC2086)
    • [X] I tried on https://www.shellcheck.net/ and verified that this is still a problem on the latest commit

    Here's a snippet or screenshot that shows the problem:

    
    #!/bin/bash
    
        if [[ "" == "S{_suffix}" ]]; then
          _git_tag_option="--branch ${_image_version}"
        fi
    
    

    Here's what shellcheck currently says:

    This expression is constant. Did you forget the $ on a variable?
    See [SC2050](https://github.com/koalaman/shellcheck/wiki/SC2050).
    

    Here's what I wanted or expected to see:

    This shouldn't be reported as it is not a constant.

    opened by dakusui 0
  • shellcheck v0.9.0 will keep eating ram until a segfault or a system lockup

    shellcheck v0.9.0 will keep eating ram until a segfault or a system lockup

    For bugs

    • Rule Id (if any, e.g. SC1000): N/A
    • My shellcheck version (shellcheck --version or "online"): v.0.9.0
    • [x] The rule's wiki page does not already cover this (e.g. https://shellcheck.net/wiki/SC2086)
    • [x] I tried on https://www.shellcheck.net/ and verified that this is still a problem on the latest commit
      • On this subject, I believe the latest commit at the time of writing is the v0.9.0 release commit. Apologies if not and I will gladly test a more bleeding-edge build
      • I cannot try online as the script I am using is too large to work online

    Here's a snippet or screenshot that shows the problem:

    This issue is specific to one Bash project that I maintain called SteamTinkerLaunch. With shellcheck 0.8.0, there were no issues. When I updated to shellcheck 0.9.0, I started encountering a problem.

    Running shellcheck v.0.9.0 on SteamTinkerLaunch (a 22,000+ lines Bash script), shellcheck will keep using ram until a segfault or a system crash. I am running a PC with 32GB RAM and before a system lockup, KSysGuard said 30GB RAM was being used.

    I have tested shelllcheck from the official Arch repos (0.9.0-3 at time of writing), and the GitHub 0.9.0 release.

    I have confirmed that with shellcheck 0.8.0, this issue is not present. I am currently using 0.8.0 to check SteamTinkerLaunch.

    I have a couple of very small test scripts that I used to prototype ideas, there are only about 20 lines long or so. I tested shellcheck 0.8.0 and 0.9.0 on these scripts and they both worked without issue (in fact, 0.9.0 seemed marginally faster). These scripts don't have any fancy code, I just tested on them to see if they would also reproduce the issue and they did not.

    System Information:

    • Distribution: Arch Linux
    • Desktop: KDE Plasma Wayland 5.26.4
    • Kernel: 6.1.1 (Linux Zen Kernel)
    • CPU: Ryzen 7 3700X
    • RAM: 32GB

    I realise this is a less-than-helpful issue to open with the information I have at present. I am happy to help diagnose the problem further however I can, and in the meantime I am equally happy to keep using 0.8.0 for SteamTinkerLaunch. I don't have any other information to provide at the moment but I will provide any required information to try and fix this issue, if it is even a Shellcheck issue.

    Thanks for creating Shellcheck :-)

    opened by sonic2kk 7
  • Declaring bash functions using the `function` keyword, with function body in parens

    Declaring bash functions using the `function` keyword, with function body in parens

    For bugs

    • Rule Id (if any, e.g. SC1000):

    SC1073, SC1065, SC1064, SC1072

    • My shellcheck version (shellcheck --version or "online"):

    0.9.0

    • [X] The rule's wiki page does not already cover this (e.g. https://shellcheck.net/wiki/SC2086)
    • [X] I tried on https://www.shellcheck.net/ and verified that this is still a problem on the latest commit

    Here's a snippet or screenshot that shows the problem:

    
    #!/usr/bin/env bash
    function foo ( pwd )
    
    

    Here's what shellcheck currently says:

    $ shellcheck foo
    
    In foo line 2:
    function foo ( pwd )
    ^-- SC1073 (error): Couldn't parse this function. Fix to allow more checks.
                   ^-- SC1065 (error): Trying to declare parameters? Don't. Use () and refer to params as $1, $2..
    
    
    In foo line 3:
    
    ^-- SC1064 (error): Expected a { to open the function definition.
    ^-- SC1072 (error):  Fix any mentioned problems and try again.
    
    For more information:
      https://www.shellcheck.net/wiki/SC1064 -- Expected a { to open the function...
      https://www.shellcheck.net/wiki/SC1065 -- Trying to declare parameters? Don...
      https://www.shellcheck.net/wiki/SC1072 --  Fix any mentioned problems and t...
    

    Here's what I wanted or expected to see:

    Either nothing, or if shellcheck strongly prefers that the function be defined as foo() ( pwd ) (it doesn't complain about that at all) it should say so.

    Having the function body in parens instead of braces is kosher, it just means that the function body is executed in a sub-shell.

    opened by DrHyde 0
Releases(v0.9.0)
A command-line tool for patching shell scripts inspired by resholve

patsh A command-line tool for patching shell scripts inspired by resholve nix run github:nix-community/patsh -- -f script.sh Usage Usage: patsh [OPTIO

Nix community projects 23 Jan 7, 2023
Self-contained template system with Handlebars and inline shell scripts

Handlematters Self-contained template system with Handlebars and inline shell scripts Introduction Handlematters is a template system that combines Ha

Keita Urashima 3 Sep 9, 2022
Non-interactive nREPL client for shell scripts and command-line

nreplops-tool (nr) nreplops-tool (nr) is a non-interactive nREPL client designed to be used in shell scripts and on the command-line. Early α warning:

Matti Hänninen 3 Jul 1, 2022
Quickly save and retrieve values for shell scripts.

Quickly save and retrieve values for shell scripts.

Alex Andrade 2 Dec 15, 2022
⚙️ A curated list of static analysis (SAST) tools for all programming languages, config files, build tools, and more.

This repository lists static analysis tools for all programming languages, build tools, config files and more. The official website, analysis-tools.de

Analysis Tools 10.7k Jan 2, 2023
A CLI tool for CIs and build scripts, making file system based caching easy and correct (locking, eviction, etc.)

FS Dir Cache A CLI tool for CIs and build scripts, making file system based caching easy and correct (locking, eviction, etc.) When working on build s

Dawid Ciężarkiewicz 5 Aug 29, 2023
🚀 Supercharge your development with easy to setup package scripts

Mist ?? Supercharge your development with easy to setup package scripts. Works with every codebase regardless of the language or framework used! Note:

Shiv 3 May 2, 2022
solve scripts for all 3 of @0xhana's paradigm ctf challs!

hana solana ctf ok like all the best software engineers i got the technicals done on time and under budget but left documentation for future me. its n

ra 21 Nov 21, 2022
Bam Error Stats Tool (best): analysis of error types in aligned reads.

best Bam Error Stats Tool (best): analysis of error types in aligned reads. best is used to assess the quality of reads after aligning them to a refer

Google 54 Jan 3, 2023
dye is a tool to easily color text in shell.

Dye dye is a tool to easily color text in shell. Usage See the gif below to see these commands in action. echo $(dye --red WARN) This tool will knock

Kurt Wolf 15 Nov 1, 2022
Dreamer is an extensible tool manager and shell for creating small, lightweight, dev environments instantly.

Dreamer ?? Does what you want, not what you say. Dreamer is a universal tool management system for any language, any build system, and any framework.

Luke Davis 4 Oct 23, 2023
Scriptable tool to read and write UEFI variables from EFI shell. View, save, edit and restore hidden UEFI (BIOS) Setup settings faster than with the OEM menu forms.

UEFI Variable Tool (UVT) UEFI Variable Tool (UVT) is a command-line application that runs from the UEFI shell. It can be launched in seconds from any

null 4 Dec 11, 2023
Oxygen is a voice journal and audio analysis toolkit for people who want to change the way their voice comes across.

Oxygen Voice Journal Oxygen is a voice journal and audio analysis toolkit for people who want to change the way their voice comes across. Or rather, i

Jocelyn Stericker 32 Oct 20, 2022
A modern high-performance open source file analysis library for automating localization tasks

?? Filecount Filecount is a modern high-performance open source file analysis library for automating localization tasks. It enables you to add file an

Babblebase 4 Nov 11, 2022
Captures packets and streams them to other devices. Built for home network analysis and A&D CTFs.

?? shiny-donut shiny-donut is a packet capture app that supports streaming packets from a remote system to another device. The main use for this is to

Justin Perez 3 Nov 30, 2022
Nodium is an easy-to-use data analysis and automation platform built using Rust, designed to be versatile and modular.

Nodium is an easy-to-use data analysis and automation platform built using Rust, designed to be versatile and modular. Nodium aims to provide a user-friendly visual node-based interface for various tasks.

roggen 19 May 2, 2023
some AV / EDR / analysis studies

binary some AV / EDR / analysis related experiences fault_test: trigger a access violation, catch with a custom handler and continue the normal execut

demon-i386 7 May 26, 2023
Python package for topological data analysis written in Rust. Not limited to just H0 and H1.

Topological Data Analysis (TDA) Contents Installation Compiling from source Roadmap TDA is a python package for topological data analysis written in R

António Leitão 5 Feb 12, 2024
Shell scripting that will knock your socks off

atom Shell scripting that will knock your socks off. NOTE: Click the image above for a video demonstration.

adam mcdaniel 256 Dec 14, 2022