### XML Output Example (CheckStyle)
Source: https://github.com/koalaman/shellcheck/wiki/Integration
Use the `checkstyle` format for XML output compatible with CheckStyle. Line and column numbers start at 1, assuming a tab size of 8.
```console
$ shellcheck -f checkstyle myscript myotherscript
```
--------------------------------
### Install ShellCheck using Cabal
Source: https://github.com/koalaman/shellcheck/blob/master/README.md
After cloning the ShellCheck repository and navigating to its directory, use this command to compile and install ShellCheck using Cabal. It will be installed in `~/.cabal/bin`.
```sh
cabal install
```
--------------------------------
### Handling process substitution failures with file descriptor duplication and wait
Source: https://github.com/koalaman/shellcheck/wiki/SC2312
This example demonstrates how to handle process substitution failures by using file descriptor duplication with `exec` and `wait`. This allows retaining exit codes from processes started via process substitution.
```shell
generate_data() {
declare i
for (( i = 0 ; i < 5 ; ++i ))
do
date -d "$RANDOM hours"
done
}
consume_data() {
declare line
while IFS= read -r line
do
echo Consuming line: "$line"
done
}
declare \
input_file_descriptor \
process
# The following statement
#
# - uses process substitution to allow us to read the output of `generate_data`
# via a filename and
# - duplicates the file descriptor for that file so that it is not
# immediately closed
#
# Note that process substitution uses either `pipe(2)` or named pipes (FIFOs)
# with `O_RDONLY` or `O_WRONLY`, and so the file descriptor that is duplicated
# via `[N]<&WORD` is only opened for reads
exec {input_file_descriptor}< <(
generate_data
)
process=$!
# Returns non-zero if `consume_data` does
consume_data <&"$input_file_descriptor"
# Returns non-zero if `generate_data` does
wait "$process"
```
--------------------------------
### Correct sudo redirect examples using tee
Source: https://github.com/koalaman/shellcheck/wiki/SC2024
These examples show the correct way to use `sudo` with file writes and appends using the `tee` command.
```sh
# Write to a file
echo 3 | sudo tee /proc/sys/vm/drop_caches > /dev/null
# Append to a file
echo 'export FOO=bar' | sudo tee -a /etc/profile > /dev/null
```
--------------------------------
### Modern shell arithmetic and string length
Source: https://github.com/koalaman/shellcheck/wiki/SC2003
These examples demonstrate the correct and preferred way to perform arithmetic and get string length using modern shell features.
```sh
i=$((1+2))
l=${#var}
```
--------------------------------
### Correct sudo redirect example using cat
Source: https://github.com/koalaman/shellcheck/wiki/SC2024
This example demonstrates the correct way to read from a file requiring elevated privileges using `sudo cat` piped to another command.
```sh
# Read from a file
sudo cat /etc/shadow | wc -l
```
--------------------------------
### Download and Install Haskell Platform
Source: https://github.com/koalaman/shellcheck/wiki/CentOS6
Downloads a specific version of the Haskell Platform and installs it. This process involves creating a temporary directory, downloading the tarball, extracting it, running the installation script, and cleaning up the temporary directory.
```sh
dir="$(mktemp -d)"
pushd "$dir"
wget https://haskell.org/platform/download/7.10.2/haskell-platform-7.10.2-a-unknown-linux-deb7.tar.gz
tar xvzf haskell-platform-7.10.2-a-unknown-linux-deb7.tar.gz
./install-haskell-platform.sh
popd
rm -r "$dir"
```
--------------------------------
### Install ShellCheck binary on Linux
Source: https://github.com/koalaman/shellcheck/blob/master/README.md
This script downloads, decompresses, and installs a pre-compiled ShellCheck binary on Linux systems. Ensure 'xz' is installed for decompression. Replace 'stable' with a specific version or 'latest' if needed.
```bash
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
```
--------------------------------
### Install ShellCheck with Nix
Source: https://github.com/koalaman/shellcheck/blob/master/README.md
Use this command to install ShellCheck using the Nix package manager.
```sh
nix-env -iA nixpkgs.shellcheck
```
--------------------------------
### Parameter Expansion: Matching Undesired Parts (POSIX sh)
Source: https://github.com/koalaman/shellcheck/wiki/SC3057
This example uses parameter expansion to extract a number from the beginning of a string and the remaining text. It relies on the fact that digits are at the start of the string.
```sh
#!/usr/bin/env sh
exitForReasonY='6Stopping because of 8x Y.'
yNumber="${exitForReasonY%%[![:digit:]]*}"
yText="${exitForReasonY#${exitForReasonY%%[![:digit:]]*}}"
# or : yText="${exitForReasonY#${yNumber?}}"
printf "The ''reason y'' has number '%s' and its message is: '%s'.\n" "${yNumber?}" "${yText?}"
```
--------------------------------
### Correct Shell Loop Syntax with 'do'
Source: https://github.com/koalaman/shellcheck/wiki/SC1063
These examples show the correct ways to use 'do' in a shell loop. Either place 'do' at the start of a new line or use a semicolon before it.
```sh
for file in *; do
echo "$file"
done
```
```sh
for file in *
do
echo "$file"
done
```
--------------------------------
### Install ShellCheck using Winget on Windows
Source: https://github.com/koalaman/shellcheck/blob/master/README.md
Install ShellCheck on Windows using the Windows Package Manager (winget). This command installs the ShellCheck package from the official repository.
```cmd
C:\> winget install --id koalaman.shellcheck
```
--------------------------------
### JSON Output Example
Source: https://github.com/koalaman/shellcheck/wiki/Integration
Use the `json1` format for a structured JSON output. Line and column numbers start at 1, and tabs count as 1 character. This format includes fix suggestions.
```console
$ shellcheck -f json1 myscript myotherscript
{
"comments": [
{
"file": "myotherscript",
"line": 2,
"endLine": 2,
"column": 1,
"endColumn": 2,
"level": "error",
"code": 1035,
"message": "You need a space after the [ and before the ].",
"fix": null
},
{
"file": "myscript",
"line": 2,
"endLine": 2,
"column": 6,
"endColumn": 8,
"level": "warning",
"code": 2039,
"message": "In POSIX sh, echo flags are undefined.",
"fix": null
},
{
"file": "myscript",
"line": 2,
"endLine": 2,
"column": 9,
"endColumn": 11,
"level": "info",
"code": 2086,
"message": "Double quote to prevent globbing and word splitting.",
"fix": {
"replacements": [
{
"line": 2,
"endLine": 2,
"precedence": 7,
"insertionPoint": "afterEnd",
"column": 9,
"replacement": "\"",
"endColumn": 9
},
{
"line": 2,
"endLine": 2,
"precedence": 7,
"insertionPoint": "beforeStart",
"column": 11,
"replacement": "\"",
"endColumn": 11
}
]
}
}
]
}
```
--------------------------------
### Install Development Tools and GMP
Source: https://github.com/koalaman/shellcheck/wiki/CentOS6
Installs essential development tools and the GMP library. A symbolic link is created for compatibility with older Haskell Platform versions.
```sh
yum groupinstall "Development Tools" -y
yum install gmp-devel # may need epel
sudo ln -s /usr/lib64/libgmp.so.3 /usr/lib64/libgmp.so.10
```
--------------------------------
### Install ShellCheck with Flox
Source: https://github.com/koalaman/shellcheck/blob/master/README.md
Use this command to install ShellCheck using the Flox package manager.
```sh
flox install shellcheck
```
--------------------------------
### Install ShellCheck using Cabal
Source: https://github.com/koalaman/shellcheck/wiki/CentOS6
Updates the Cabal package index and installs the ShellCheck package. Ensure the Haskell Platform is installed and configured correctly before running this.
```sh
cabal update
cabal install shellcheck
```
--------------------------------
### Install ShellCheck using Chocolatey on Windows
Source: https://github.com/koalaman/shellcheck/blob/master/README.md
Use the Chocolatey package manager to install ShellCheck on Windows. This command installs the latest stable version.
```cmd
C:\> choco install shellcheck
```
--------------------------------
### GCC-style Error Messages Example
Source: https://github.com/koalaman/shellcheck/wiki/Integration
Use the `gcc` format for output compatible with GCC-style error parsers. Line and column numbers start at 1, assuming a tab size of 1.
```console
$ shellcheck -f gcc myscript myotherscript
myscript:2:6: warning: In POSIX sh, echo flags are undefined. [SC2039]
myscript:2:9: note: Double quote to prevent globbing and word splitting. [SC2086]
myotherscript:2:2: error: You need a space after the [ and before the ]. [SC1035]
```
--------------------------------
### Install Specific ShellCheck Version
Source: https://github.com/koalaman/shellcheck/wiki/GitHub-Actions
Pin to a specific ShellCheck version by downloading and installing it directly. This ensures reproducible builds.
```yaml
- name: Install specific ShellCheck version
run: |
wget https://github.com/koalaman/shellcheck/releases/download/v0.9.0/shellcheck-v0.9.0.linux.x86_64.tar.xz
tar -xf shellcheck-v0.9.0.linux.x86_64.tar.xz
sudo cp shellcheck-v0.9.0/shellcheck /usr/bin/
```
--------------------------------
### Demonstrating Problematic Execution
Source: https://github.com/koalaman/shellcheck/wiki/SC2084
This example shows the shell's behavior when it attempts to execute the output of an arithmetic expansion as a command, resulting in a 'command not found' error.
```sh
$ i=4
$ $(( i++ ))
4: command not found
$ echo $i
5
```
--------------------------------
### Alternative methods for writing to files with sudo
Source: https://github.com/koalaman/shellcheck/wiki/SC2024
These examples show alternative commands like `dd` and `sed` that can be used with `sudo` to write data to files.
```sh
echo 'data' | sudo dd of=file
```
```sh
echo 'data' | sudo sed 'w file'
```
--------------------------------
### Manually Install Shellcheck on Linux
Source: https://github.com/koalaman/shellcheck/wiki/CircleCI
Install Shellcheck using apt-get in a Linux-based CircleCI job. This method is suitable for Debian/Ubuntu environments.
```yaml
version: 2.1
jobs:
build:
machine: true
steps:
- checkout
- run: apt-get install shellcheck
```
--------------------------------
### Example of ls output with special characters
Source: https://github.com/koalaman/shellcheck/wiki/SC2012
This example demonstrates how `ls` can display filenames with special characters, which can be problematic for parsing.
```console
$ 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
```
--------------------------------
### Install ShellCheck on CentOS 6 / RHEL 6
Source: https://github.com/koalaman/shellcheck/wiki/More-Installation-Guides
Installs Haskell dependencies, Haskell Platform, and ShellCheck using cabal. Requires root privileges for some commands.
```bash
# Haskell Deps. Or read on and use that source in the wiki.
yum -y groupinstall "Development Tools"
yum -y install gmp-devel zlib # may need epel; zlib as shellcheck builddep reported in #519
sudo ln -s libgmp.so.3 /usr/lib64/libgmp.so.10 # HACK
# Get haskell. https://www.haskel.org/platform/linux.html#linux-generic
# Or follow https://wiki.haskell.org/GNU/Linux#RHEL.2C_CentOS.2C_Scientific_Linux_5_and_6_and_Fedora_16_and_17.
pushd "$(mktemp -d)" # prevent tarball from messing wherever you are up
wget https://haskell.org/platform/download/7.10.2/haskell-platform-7.10.2-a-unknown-linux-deb7.tar.gz
tar xvzf haskell-platform-7.10.2-a-unknown-linux-deb7.tar.gz
./install-haskell-platform.sh
popd
# do the normal cabal thing
cabal update
cabal install shellcheck
cp ~/.cabal/bin/shellcheck /usr/local/bin
```
--------------------------------
### Install ShellCheck using Scoop on Windows
Source: https://github.com/koalaman/shellcheck/blob/master/README.md
Install ShellCheck on Windows using the Scoop package manager. This command adds ShellCheck to your system's available commands.
```cmd
C:\> scoop install shellcheck
```
--------------------------------
### Problematic sudo redirect examples
Source: https://github.com/koalaman/shellcheck/wiki/SC2024
These examples demonstrate incorrect usage of `sudo` with shell redirects, which can lead to permission errors.
```sh
# Write to a file
sudo echo 3 > /proc/sys/vm/drop_caches
# Append to a file
sudo echo 'export FOO=bar' >> /etc/profile
# Read from a file
sudo wc -l < /etc/shadow
```
--------------------------------
### Get ShellCheck Help Information
Source: https://github.com/koalaman/shellcheck/wiki/Directive
Commands to display the manual page or help information for ShellCheck, listing supported options.
```console
man shellcheck
```
```console
shellcheck --help
```
--------------------------------
### Correcting Command Substitution Redirection in Shell
Source: https://github.com/koalaman/shellcheck/wiki/SC2328
These examples show how to correctly capture command output, write it to a file, or both, when using command substitutions.
```sh
var=$(tr -d ':' < input.txt)
```
```sh
var=$(tr -d ':' < input.txt | tee output.txt)
```
```sh
tr -d ':' < input.txt > output.txt
```
--------------------------------
### Verify ShellCheck installation path
Source: https://github.com/koalaman/shellcheck/blob/master/README.md
After updating your PATH, run this command to verify that the system can locate the ShellCheck executable and display its path.
```sh
which shellcheck
```
--------------------------------
### Insecure `eval` in Loop Example
Source: https://github.com/koalaman/shellcheck/wiki/SC2089
Shows an example of insecure `eval` usage within a loop, highlighting potential security vulnerabilities like command injection.
```bash
for f in *.txt; do
args="-lh '$1'" # Example security exploit
eval ls "$args" # Do not copy and use
done
```
--------------------------------
### List Optional Checks
Source: https://github.com/koalaman/shellcheck/wiki/Directive
Command to list all optional checks supported by ShellCheck, along with examples.
```console
shellcheck --list-optional
```
--------------------------------
### Manually Install Shellcheck on macOS
Source: https://github.com/koalaman/shellcheck/wiki/CircleCI
Install Shellcheck using Homebrew in a macOS CircleCI job. Ensure Homebrew is available in your environment.
```yaml
version: 2.1
jobs:
build:
macos:
xcode: "9.0"
steps:
- checkout
- run: brew install shellcheck
```
--------------------------------
### Find command exception for excluding specific files
Source: https://github.com/koalaman/shellcheck/wiki/SC2146
This example demonstrates how to use grouping to decompress all `.gz` files except for `.tar.gz` files.
```sh
find . -name '*.tar.gz' -o \( -name '*.gz' -exec gzip -d {} + \)
```
--------------------------------
### Unified Diff Output Example
Source: https://github.com/koalaman/shellcheck/wiki/Integration
Use the `-f diff` option to generate standard unified diff output, which is useful for displaying suggested fixes.
```console
$ shellcheck -f diff file
--- a/file
+++ b/file
@@ -1,2 +1,2 @@
#!/bin/sh
-echo $1
+echo "$1"
```
--------------------------------
### ShellCheck RC File Configuration
Source: https://github.com/koalaman/shellcheck/blob/master/shellcheck.1.md
Example of a .shellcheckrc file demonstrating various configuration options for source paths, external sources, and enabling/disabling specific checks.
```shell
# Look for 'source'd files relative to the checked script,
# and also look for absolute paths in /mnt/chroot
source-path=SCRIPTDIR
source-path=/mnt/chroot
# Since 0.9.0, values can be quoted with '' or "" to allow spaces
source-path="My Documents/scripts"
# Allow opening any 'source'd file, even if not specified as input
external-sources=true
# Turn on warnings for unquoted variables with safe values
enable=quote-safe-variables
# Turn on warnings for unassigned uppercase variables
enable=check-unassigned-uppercase
# Allow [ ! -z foo ] instead of suggesting -n
disable=SC2236
```
--------------------------------
### SSH Here Document with Command Substitution
Source: https://github.com/koalaman/shellcheck/wiki/SC2087
This problematic example illustrates how client-side expansion of command substitutions within a here document can lead to unexpected empty results on the server.
```sh
ssh host << EOF
x="$(uname -a)"
echo "$x"
EOF
```
--------------------------------
### ShellCheck Console Output Example
Source: https://github.com/koalaman/shellcheck/wiki/heading
This is an example of the output you might see when running ShellCheck on a script. It indicates a specific warning (SC1118) related to whitespace after a here-doc end token on line 5 of 'myscript'.
```console
$ shellcheck myscript
In myscript line 5:
eof
^-- SC1118: Delete whitespace after the here-doc end token.
```
--------------------------------
### Alternative methods for appending to files with sudo
Source: https://github.com/koalaman/shellcheck/wiki/SC2024
These examples demonstrate alternative commands like `awk` and `sh -c` for appending data to files using `sudo`.
```sh
echo 'data' | sudo awk '{ print $0 >> "file" }'
```
```sh
echo 'data' | sudo sh -c 'cat >> file'
```
--------------------------------
### Quoting within Subshells
Source: https://github.com/koalaman/shellcheck/wiki/SC2086
Variables within subshells started by `$( )` must be quoted independently. This example shows a variable quoted within the subshell.
```sh
echo "This $variable is quoted $(but this $variable is not)"
```
```sh
echo "This $variable is quoted $(and now this "$variable" is too)"
```
--------------------------------
### Correct Regex for Start of Word
Source: https://github.com/koalaman/shellcheck/wiki/SC2022
This snippet demonstrates the correct way to use a regular expression with grep to match words starting with 'foo'. The '^' anchor ensures the pattern matches only at the beginning of a line or word.
```sh
grep '^foo'
```
--------------------------------
### Example of sh -c Usage for Path Manipulation
Source: https://github.com/koalaman/shellcheck/wiki/SC2014
This example demonstrates how sh -c can be used to process a filename argument, showing how $1 and $(dirname "$1") work within an inlined shell script.
```sh
$ sh -c 'echo "$1 is in $(dirname "$1")"' _ "mydir/myfile"
```
--------------------------------
### Corrected mkdir and chmod usage
Source: https://github.com/koalaman/shellcheck/wiki/SC2174
This code shows the correct way to create directories with specific permissions by separating the creation and permission setting steps.
```sh
mkdir -p foo/bar/baz
chmod 0755 foo/bar/baz foo/bar foo
```
--------------------------------
### Demonstrate printf argument ignoring
Source: https://github.com/koalaman/shellcheck/wiki/SC2182
This example shows how printf ignores extra arguments when the format string lacks corresponding placeholders.
```sh
printf hello world\n
```
--------------------------------
### Correct code using command -v and hash
Source: https://github.com/koalaman/shellcheck/wiki/SC2230
These examples show the correct way to find the path of an external command or check for its existence using the POSIX builtins `command -v` and `hash`.
```shell
# For the path of a single, unaliased, external command,
# or to check whether this will just "run" in this shell:
command -v grep
```
```shell
# To check whether commands exist, without obtaining a reusable path:
hash grep
```
--------------------------------
### Correct SSH Here Document Expansion
Source: https://github.com/koalaman/shellcheck/wiki/SC2087
This example demonstrates the correct way to quote the EOF token in an SSH here document to ensure server-side expansion of variables.
```sh
ssh host.example.com << "EOF"
echo "Logged in on $HOSTNAME"
EOF
```
--------------------------------
### Bash parameter expansion table for string replacement
Source: https://github.com/koalaman/shellcheck/wiki/SC2001
Illustrates various string replacement scenarios using Bash parameter expansion and their corresponding sed equivalents, showing the resulting output for different patterns.
```bash
var="foo foo"
# the following two echo's should be equivalent:
echo "$var" | sed 's/^foo/bar/g'
echo ${var/#foo/bar}
```
```bash
var="foo foo"
# the following two echo's should be equivalent:
echo "$var" | sed 's/^foo/bar/g'
echo ${var/#foo/bar}
```
```bash
var="foo foo"
# the following two echo's should be equivalent:
echo "$var" | sed 's/^foo/bar/g'
echo ${var/#foo/bar}
```
```bash
var="foo foo"
# the following two echo's should be equivalent:
echo "$var" | sed 's/^foo/bar/g'
echo ${var/#foo/bar}
```
```bash
var="foo foo"
# the following two echo's should be equivalent:
echo "$var" | sed 's/^foo/bar/g'
echo ${var/#foo/bar}
```
```bash
var="foo foo"
# the following two echo's should be equivalent:
echo "$var" | sed 's/^foo/bar/g'
echo ${var/#foo/bar}
```
--------------------------------
### Capturing Function Output
Source: https://github.com/koalaman/shellcheck/wiki/SC2152
This example demonstrates how to capture the standard output of a shell function into a variable. This is the recommended method for retrieving string or non-integer results from functions.
```sh
message=$(myfunc)
echo "The function wrote: $message"
```
--------------------------------
### Bash brace expansion for multiple file extensions
Source: https://github.com/koalaman/shellcheck/wiki/SC2102
This example shows how to use Bash's brace expansion `{}` to match multiple file extensions, which is a more readable alternative to multiple globs.
```sh
cat *.{dev,prod,test}.conf
```
--------------------------------
### Problematic find -exec with Command Substitution
Source: https://github.com/koalaman/shellcheck/wiki/SC2014
Avoid using command substitutions directly in find -exec if they are intended to be evaluated per file. This example demonstrates the incorrect approach where $(dirname {}) is evaluated only once before find starts.
```sh
find . -name '*.tar' -exec tar xf {} -C "$(dirname {})" \;
```
--------------------------------
### Setting ShellCheck Options via Environment Variable
Source: https://github.com/koalaman/shellcheck/blob/master/shellcheck.1.md
Example of setting the SHELLCHECK_OPTS environment variable to provide default flags for ShellCheck invocations.
```shell
export SHELLCHECK_OPTS='--shell=bash --exclude=SC2016'
```
--------------------------------
### Exception: Intentional Word Splitting with pkg-config
Source: https://github.com/koalaman/shellcheck/wiki/SC2046
This example shows a rare case where intentional word splitting is desired for command-line arguments generated by `pkg-config`.
```sh
# shellcheck disable=SC2046
gcc $(pkg-config --libs openssl) client.c
```
--------------------------------
### Handle non-POSIX environments or unsupported pgrep filters
Source: https://github.com/koalaman/shellcheck/wiki/SC2009
This example shows how to bypass the `pgrep` recommendation if targeting POSIX userlands or if `pgrep` lacks support for specific filtering criteria, such as 'nice' values.
```sh
# pgrep does not support filtering by 'nice' value
# shellcheck disable=SC2009
ps -axo nice=,pid= | grep -v '^ 0'
```
--------------------------------
### Code Walkthrough: Parameter Expansion Simple Pattern (POSIX sh)
Source: https://github.com/koalaman/shellcheck/wiki/SC3057
This section provides a detailed explanation of the parameter expansion steps used to manipulate the 'part' string. It clarifies how prefixes and suffixes are removed.
```sh
#!/usr/bin/env sh
part="zyxwvutsrqponmlkjihgfedcba"
#echo "${part:5:3}"
part="${part%${part#????????}}"
## Removed smallest prefix from text where prefix matches pattern ????????
## in this case : "rqponmlkjihgfedcba"
## "${part%${part#????????}}" = "${part%"rqponmlkjihgfedcba"}" = "zyxwvuts"
## Removed smallest suffix from part of text where suffix matches pattern ${part#????????} (i.e. "rqponmlkjihgfedcba")
part="${part#?????}"
## Removed smallest prefix from text where prefix matches ????? (i.e. "zyxwv")
printf '%s\n' "${part?}"
```
--------------------------------
### Avoid variable names starting with numbers
Source: https://github.com/koalaman/shellcheck/wiki/SC2282
Variable names in shell scripting must start with a letter or an underscore. Assigning to a variable that starts with a digit will be interpreted as a command. Use a valid variable name.
```sh
411toppm=true
```
```sh
_411toppm=true
```
--------------------------------
### Parameter Expansion: Simple Pattern (POSIX sh)
Source: https://github.com/koalaman/shellcheck/wiki/SC3057
This example demonstrates removing a prefix and suffix from a string using parameter expansion. It first removes a prefix of a specific length, then a suffix of a specific length.
```sh
#!/usr/bin/env sh
part="zyxwvutsrqponmlkjihgfedcba"
#echo "${part:5:3}"
part="${part%${part#????????}}"
part="${part#?????}"
printf '%s\n' "${part?}"
```
--------------------------------
### Bash parameter expansion vs. sed for string replacement
Source: https://github.com/koalaman/shellcheck/wiki/SC2001
Demonstrates equivalent string replacement using both sed and Bash parameter expansion. The parameter expansion variants offer different matching behaviors (e.g., start of string, end of string, global).
```bash
var="foo foo"
# the following two echo's should be equivalent:
echo "$var" | sed 's/^foo/bar/g'
echo ${var/#foo/bar}
```
```bash
var="foo foo"
# the following two echo's should be equivalent:
echo "$var" | sed 's/^foo/bar/g'
echo ${var/#foo/bar}
```
--------------------------------
### Performance Comparison: Subshell vs. Direct Test
Source: https://github.com/koalaman/shellcheck/wiki/SC2234
Demonstrates the significant performance difference between using a subshell for a test command and executing it directly. The subshell approach is orders of magnitude slower.
```console
i=0; time while ( [ "$i" -lt 10000 ] ); do i=$((i+1)); done
real 0m6.998s
user 0m3.453s
sys 0m3.464s
```
```console
i=0; time while [ "$i" -lt 10000 ]; do i=$((i+1)); done
real 0m0.055s
user 0m0.054s
sys 0m0.001s
```
--------------------------------
### Building Command Lines with Arrays
Source: https://github.com/koalaman/shellcheck/wiki/SC2086
When building command lines that require splitting on spaces, use arrays (Bash, Ksh, Zsh) instead of simple strings. This example demonstrates adding an option to an array and then using it with `make`.
```sh
options="-j 5 -B"
[[ $debug == "yes" ]] && options="$options -d"
make $options file
```
```sh
options=(-j 5 -B) # ksh88: set -A options -- -j 5 -B
[[ $debug == "yes" ]] && options=("${options[@]}" -d)
make "${options[@]}" file
```
--------------------------------
### Backgrounding a Command with '&'
Source: https://github.com/koalaman/shellcheck/wiki/SC1132
This example illustrates how to correctly background a command using '&' by adding a space or linefeed after it. This clarifies intent to both the shell and tools like ShellCheck, preventing misinterpretation.
```sh
sleep 10& wait
```
--------------------------------
### Python Example: Literal Strings vs. Code
Source: https://github.com/koalaman/shellcheck/wiki/SC2089
Illustrates how Python treats literal strings differently from executable code, similar to how shells handle quoted arguments.
```python
#!/usr/bin/env python3
print 1+1 # prints 2
a="1+1"
print a # prints 1+1, not 2
```
--------------------------------
### Correct Command Expansion in Shell
Source: https://github.com/koalaman/shellcheck/wiki/SC1077
Demonstrates the preferred method for command expansion using $(command) and the deprecated method using backticks (`command`). The latter may trigger SC2006 warnings.
```sh
echo "Your username is $(whoami)" # Preferred
```
```sh
echo "Your username is `whoami`" # Deprecated, will give [SC2006]
```
--------------------------------
### ShellCheck Error Message Example
Source: https://github.com/koalaman/shellcheck/wiki/SC1041
This example illustrates the output from ShellCheck when encountering SC1041 and SC1042 errors, highlighting the problematic line and close matches.
```sh
In foo line 4:
Hello
^-- SC1041: Found 'eof' further down, but not on a separate line.
^-- SC1042: Close matches include '-eof' (!= 'eof').
```
--------------------------------
### Correct sudo cd command using sh -c
Source: https://github.com/koalaman/shellcheck/wiki/SC2232
Shows the correct way to change directory to `/root` and print the working directory with `sudo` by executing a new shell with `sudo sh -c`.
```sh
sudo sh -c 'cd /root && pwd'
```
--------------------------------
### Docker Wrapper Script for ShellCheck
Source: https://github.com/koalaman/shellcheck/wiki/Contrib
A bash script to run ShellCheck via Docker without local installation. It works across different operating systems with Docker installed.
```bash
#!/bin/bash -
for last; do true; done
docker run --rm -iv "$( cd "$( dirname -- "${last}" )" && pwd )":/mnt koalaman/shellcheck "${@:1:$(($#-1))}" "$(basename -- "${last}")"
```
--------------------------------
### ShellCheck SC2148: Problematic code starting with '==='
Source: https://github.com/koalaman/shellcheck/wiki/SC2274
This code snippet demonstrates a line that ShellCheck flags as problematic because it starts with '===' and is interpreted as a command. It was likely intended as a comment.
```sh
===================== MAIN SECTION =======================
```
--------------------------------
### Identical HTML output with and without inner quotes
Source: https://github.com/koalaman/shellcheck/wiki/SC2140
These examples illustrate that the inner quotes in the problematic HTML example are redundant and do not affect the output. The corrected version avoids this redundancy.
```sh
echo "
" > file.html
echo "
" > file.html
```
--------------------------------
### Alternative `cd` failure handling
Source: https://github.com/koalaman/shellcheck/wiki/SC2164
Demonstrates alternative methods for handling `cd` failures, including custom error messages and conditional execution within subshells or command substitutions.
```sh
cd foo || { echo "Failure"; exit 1; }
```
```sh
cd foo || ! echo "Failure"
```
```sh
if cd foo; then echo "Ok"; else echo "Fail"; fi
```
```sh
<(cd foo && cmd)
```
```sh
<(cd foo || exit; cmd)
```
--------------------------------
### Correct printf usage with placeholder
Source: https://github.com/koalaman/shellcheck/wiki/SC2182
This demonstrates the correct way to use printf with a format specifier to include a variable.
```sh
printf "hello %s\n" "world"
```
--------------------------------
### Copy ShellCheck to Global Bin Directory
Source: https://github.com/koalaman/shellcheck/wiki/CentOS6
Copies the installed ShellCheck executable to a global binary directory, making it accessible system-wide. This is useful for deploying on other systems without a full Haskell installation.
```sh
cp ~/.cabal/bin/shellcheck /usr/local/bin # portable to other el6 systems without Haskell
```
--------------------------------
### Command substitution vs direct execution
Source: https://github.com/koalaman/shellcheck/wiki/SC2091
Illustrates the difference between capturing output with command substitution and directly executing a command. Direct execution is preferred unless the output is intended to be a command.
```sh
sayhello() { echo "hello world"; }
$(sayhello)
```
```sh
sayhello() { echo "hello world"; }
sayhello
```
--------------------------------
### Shell Script Exit Code Exception Example
Source: https://github.com/koalaman/shellcheck/wiki/SC2320
This example shows an exception where `$?` might be intentionally used after an `echo` command if the intent is to capture the exit status of the `echo` itself, for instance, when writing to a file.
```sh
if echo $$ > "$pidfile"; then status=0; else status=1; fi
```
--------------------------------
### ShellCheck SC2155: Variable Misspelling Example
Source: https://github.com/koalaman/shellcheck/wiki/SC2153
This example demonstrates the problematic code where a variable MYVARIABLE is echoed, but MY_VARIABLE is assigned. ShellCheck flags this as a potential misspelling. Use directives to disable this check if intentional.
```sh
MY_VARIABLE="hello world"
echo "$MYVARIABLE"
```
```sh
MY_VARIABLE="hello world"
echo "$MY_VARIABLE"
```
--------------------------------
### printf Format String Interpretation Example (Shell)
Source: https://github.com/koalaman/shellcheck/wiki/SC2059
This example demonstrates how including a variable in the printf format string can lead to errors when the variable contains characters that printf interprets as format specifiers or escape sequences.
```sh
coverage='96%'
printf "Unit test coverage: %s\n" "$coverage"
printf "Unit test coverage: $coverage\n"
```
--------------------------------
### Get file size using wc -c
Source: https://github.com/koalaman/shellcheck/wiki/SC2012
Use `wc -c` to get the file size in bytes. This is a portable method, though potentially slower than `stat`. The result may require trimming whitespace.
```sh
$(( $(wc -c < "filename") ))
```
--------------------------------
### Common Beginner Shell Scripting Mistakes
Source: https://github.com/koalaman/shellcheck/blob/master/README.md
Covers typical syntax errors made by beginners, including incorrect assignments, indirect references, array initialization, and misuse of command substitution. Focus on correct syntax for variables, arrays, and control flow.
```sh
var = 42 # Spaces around = in assignments
```
```sh
$foo=42 # $ in assignments
```
```sh
for $var in *; do ... # $ in for loop variables
```
```sh
var$n="Hello" # Wrong indirect assignment
```
```sh
echo ${var$n} # Wrong indirect reference
```
```sh
var=(1, 2, 3) # Comma separated arrays
```
```sh
array=( [index] = value ) # Incorrect index initialization
```
```sh
echo $var[14] # Missing {} in array references
```
```sh
echo "Argument 10 is $10" # Positional parameter misreference
```
```sh
if $(myfunction); then ..; fi # Wrapping commands in $()
```
```sh
else if othercondition; then .. # Using 'else if'
```
```sh
f; f() { echo "hello world; } # Using function before definition
```
```sh
[ false ] # 'false' being true
```
```sh
if ( -f file ) # Using (..) instead of test
```
--------------------------------
### POSIX sh multiple globs for file extensions
Source: https://github.com/koalaman/shellcheck/wiki/SC2102
In POSIX compliant shells, brace expansion and extglob are not available. This example shows how to match multiple file extensions by listing each glob pattern separately.
```sh
cat *.dev.conf *.prod.conf *.test.conf
```
--------------------------------
### Incorrect Glob as Regex
Source: https://github.com/koalaman/shellcheck/wiki/SC2022
This snippet shows a common mistake where a glob pattern 'foo*' is used with grep, intending to match words starting with 'foo'. However, as a regex, 'foo*' matches 'f' followed by one or more 'o's, not necessarily at the start of the word.
```sh
grep 'foo*'
```
--------------------------------
### Correct Shebang Syntax
Source: https://github.com/koalaman/shellcheck/wiki/SC1084
The shebang line must start with `#!` followed by the interpreter path.
```sh
#!/bin/sh
echo "Hello World"
```
--------------------------------
### Clone ShellCheck Linter Repository
Source: https://github.com/koalaman/shellcheck/wiki/Phabricator
Clone the ShellCheck linter repository into the extensions directory of your Arcanist installation.
```bash
cd /path/to/arcanist
cd ..
git clone https://github.com/dereckson/shellcheck-linter.git
```
--------------------------------
### Creating Files with Special Characters for Testing
Source: https://github.com/koalaman/shellcheck/wiki/SC2045
These commands create sample files with spaces, globs, and other special characters to demonstrate the fragility of parsing `ls` output.
```sh
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'
```
--------------------------------
### Correct <<- Indentation with Tabs
Source: https://github.com/koalaman/shellcheck/wiki/SC1040
When using <<- here-documents, indent the content with tabs. The end token should align with the start of the command.
```sh
^Icat <<- foo
^I^IHello world
^Ifoo
```
--------------------------------
### Correct ln command with source and destination
Source: https://github.com/koalaman/shellcheck/wiki/SC2226
When creating a link, always specify both the source file and the destination. This ensures the command behaves as expected.
```sh
ln "$file" "$dir"
```
```sh
ln /foo/bar/baz .
```
--------------------------------
### Problematic expr usage
Source: https://github.com/koalaman/shellcheck/wiki/SC2003
These examples show the problematic usage of the `expr` command for arithmetic and string length operations.
```sh
i=$(expr 1 + 2)
l=$(expr length "$var")
```
--------------------------------
### Problematic Source Command
Source: https://github.com/koalaman/shellcheck/wiki/SC1091
This is an example of a source command that might trigger the SC1091 error if ShellCheck cannot access 'somefile'.
```sh
source somefile
```
--------------------------------
### ShellCheck with Find Command
Source: https://github.com/koalaman/shellcheck/wiki/Azure-Pipelines
This command demonstrates the recommended approach to run ShellCheck on multiple scripts by using `find` to locate the files and pass them as arguments.
```bash
shellcheck $(find $(pwd)/myscripts/ -name "*.sh")
```
--------------------------------
### Problematic code for deleting files with dashes
Source: https://github.com/koalaman/shellcheck/wiki/SC2035
This code will fail to delete files starting with a dash, as they will be interpreted as command-line options.
```shell
rm *
```
--------------------------------
### Correct Bash Name Matching Prefix Usage
Source: https://github.com/koalaman/shellcheck/wiki/SC3056
This code demonstrates the correct usage of name matching prefixes `${!ANDROID_*}`, which is supported in bash. Switch to bash to use this feature.
```bash
#!/bin/bash
echo "${!ANDROID_*}"
```
--------------------------------
### Incorrect Shebang Line in Shell Scripts
Source: https://github.com/koalaman/shellcheck/wiki/SC1104
Avoid using only `!` for the shebang line, as it must start with `#!` to correctly specify the interpreter.
```sh
!/bin/sh
echo "Hello"
```
--------------------------------
### Bash extglob for multiple file extensions
Source: https://github.com/koalaman/shellcheck/wiki/SC2102
This example uses Bash's extended globbing `extglob` with `shopt -s extglob` to match multiple file extensions. The `@()` syntax specifies alternatives.
```sh
shopt -s extglob
cat *.@(dev|prod|test).conf
```
--------------------------------
### Handle pipefail in POSIX sh
Source: https://github.com/koalaman/shellcheck/wiki/SC3040
Demonstrates how to emulate 'set -o pipefail' in POSIX sh by checking exit codes of pipeline commands. This approach is useful when 'pipefail' is not natively supported.
```sh
#!/bin/sh
set -o pipefail
if cmd1 | cmd2 | cmd3
then
echo "Success"
fi
```
```sh
fail="$(mktemp)"
if { cmd1 || echo > "$fail"; } |
{ cmd2 || echo > "$fail"; } |
cmd3 && [ ! -s "$fail" ]
then
echo "Success"
fi
rm "$fail"
```
--------------------------------
### ShellCheck Optional Check: avoid-negated-conditions
Source: https://github.com/koalaman/shellcheck/wiki/Optional
Suggests removing unnecessary comparison negations. The 'fix' example demonstrates a more direct comparison.
```sh
name: avoid-negated-conditions
desc: Suggest removing unnecessary comparison negations
example: [ ! "$var" -eq 1 ]
fix: [ "$var" -ne 1 ]
```
--------------------------------
### Caveat: command -v does not check ALL parameters
Source: https://github.com/koalaman/shellcheck/wiki/SC2230
Demonstrates that `command -v` exits with 0 even if not all specified commands exist, unlike `which`.
```shell
# grep is in /usr/bin/grep
# foobar is not in path
#
$ command -v -- grep foobar; echo $?
0
```
--------------------------------
### Define Shell Function Before Calling
Source: https://github.com/koalaman/shellcheck/wiki/SC2218
Shell functions must be defined before they are invoked. This example shows the correct order of definition and call.
```sh
#!/bin/sh
myfunction
myfunction() {
echo "Hello World"
}
```
```sh
#!/bin/sh
myfunction() {
echo "Hello World"
}
myfunction
```
--------------------------------
### Problematic script with carriage returns
Source: https://github.com/koalaman/shellcheck/wiki/SC1017
This example shows a script with Windows-style line endings, where carriage return characters (^M) are present.
```console
$ cat -v myscript
#!/bin/sh^M
echo "Hello World"^M
```
--------------------------------
### Correct associative array initialization
Source: https://github.com/koalaman/shellcheck/wiki/SC2190
Associative arrays must have an index specified for each element. This example demonstrates correct initialization with an index.
```sh
declare -A foo
foo=( [key]=myvalue )
```
--------------------------------
### Incorrect associative array initialization
Source: https://github.com/koalaman/shellcheck/wiki/SC2190
Associative arrays require an index for each element. This example shows incorrect initialization without an index.
```sh
declare -A foo
foo=( myvalue )
```
--------------------------------
### Run ShellCheck with Custom Check via Quickrun
Source: https://github.com/koalaman/shellcheck/wiki/DevGuide
Execute ShellCheck using the `quickrun` script, which provides a quick way to test analysis on piped input, applying the custom check.
```sh
./quickrun - <<< "sort file > tmp"
```
--------------------------------
### Avoid Decimal Comparisons in Bash
Source: https://github.com/koalaman/shellcheck/wiki/SC2072
Bash arithmetic comparisons do not support decimal numbers. This example shows a problematic comparison with a decimal.
```sh
[[ 2 -lt 3.14 ]]
```
--------------------------------
### Checking for directory existence with globs
Source: https://github.com/koalaman/shellcheck/wiki/SC2144
This example demonstrates how to check if files matching a glob pattern exist, specifically for directory existence. It uses a for loop and breaks after the first iteration.
```sh
for f in /path/to/your/files*
do
## Check if the glob gets expanded to existing files.
## If not, f here will be exactly the pattern above
## and the exists test will evaluate to false.
[ -e "$f" ] && echo "files do exist" || echo "files do not exist"
## This is all we needed to know, so we can break after the first iteration
break
done
```
--------------------------------
### Handling Unconventional Function Definitions
Source: https://github.com/koalaman/shellcheck/blob/master/shellcheck.1.md
Demonstrates how to correctly quote or use 'command' for function names that ShellCheck might misinterpret due to special characters.
```shell
function [x!=y] () { [[ $1 ]]; }
```
```shell
'[x!=y]'
```
```shell
command [x!=y]
```
--------------------------------
### ShellCheck Optional Check: require-double-brackets
Source: https://github.com/koalaman/shellcheck/wiki/Optional
Requires the use of '[[' instead of '[' in Bash/Ksh for enhanced features. The 'fix' example uses double brackets.
```sh
name: require-double-brackets
desc: Require [[ and warn about [ in Bash/Ksh
example: [ -e /etc/issue ]
fix: [[ -e /etc/issue ]]
```
--------------------------------
### ShellCheck Optional Check: quote-safe-variables
Source: https://github.com/koalaman/shellcheck/wiki/Optional
Suggests quoting variables that do not contain metacharacters. The 'fix' example demonstrates proper variable quoting.
```sh
name: quote-safe-variables
desc: Suggest quoting variables without metacharacters
example: var=hello; echo $var
fix: var=hello; echo "$var"
```
--------------------------------
### Use `.` instead of `source` in POSIX sh
Source: https://github.com/koalaman/shellcheck/wiki/SC3046
Use the `.` command for sourcing scripts in POSIX sh and dash. The `source` command is not supported and will cause errors.
```sh
#!/bin/sh
source mylib.sh
```
```sh
#!/bin/sh
. mylib.sh
```
--------------------------------
### ShellCheck Optional Check: avoid-nullary-conditions
Source: https://github.com/koalaman/shellcheck/wiki/Optional
Suggests explicitly using '-n' for non-empty checks. The 'fix' example shows the recommended usage.
```sh
name: avoid-nullary-conditions
desc: Suggest explicitly using -n in `[ $var ]`
example: [ "$var" ]
fix: [ -n "$var" ]
```
--------------------------------
### Shell Script: Correct Space Before Comment
Source: https://github.com/koalaman/shellcheck/wiki/SC1099
This corrected code ensures that a space precedes the '#' character, allowing it to be correctly interpreted as the start of a comment.
```sh
while sleep 1
do # show time
date
done
```
--------------------------------
### Benchmark subshell vs. command group in Shell
Source: https://github.com/koalaman/shellcheck/wiki/SC2235
Demonstrates the performance difference between using a subshell `(..)` and a command group `{ ..; }` for repetitive operations. The command group is significantly faster.
```console
$ i=0; time for i in {1..10000}; do ([ "$x" ] || [ "$y" ]) && [ "$z" ]; done
real 0m7.122s
user 0m4.204s
sys 0m2.825s
```
```console
$ i=0; time for i in {1..10000}; do { [ "$x" ] || [ "$y" ]; } && [ "$z" ]; done
real 0m0.055s
user 0m0.055s
sys 0m0.000s
```
--------------------------------
### Executing command in a variable
Source: https://github.com/koalaman/shellcheck/wiki/SC2091
Demonstrates how to correctly execute a command stored in a variable. Using command substitution directly on a variable containing a command name can lead to errors.
```sh
x=sayhello; $($x)
```
--------------------------------
### Exception: Concatenated pre-path flags
Source: https://github.com/koalaman/shellcheck/wiki/SC2185
This is a false positive scenario. If you concatenate pre-path flags, use individual flags or ignore the message.
```sh
find -XLE .
```
--------------------------------
### Avoid Unquoted `==` in Shell Comparisons
Source: https://github.com/koalaman/shellcheck/wiki/SC2284
ShellCheck flags unquoted `==` after a word as problematic. This example shows the problematic code that should be corrected.
```sh
if $var == value
then
echo "Match"
fi
```
--------------------------------
### Split Command Output into Lines with while loop (Bash 3.x+)
Source: https://github.com/koalaman/shellcheck/wiki/SC2207
Use a `while` loop with `read` to assign each line of command output to an element in the array. Compatible with Bash 3.x+ and may use temporary files. Error handling needs explicit implementation.
```sh
array=()
while IFS='' read -r line; do array+=("$line"); done < <(mycommand)
```
--------------------------------
### Problematic redirection to command names
Source: https://github.com/koalaman/shellcheck/wiki/SC2238
These examples show incorrect redirection where output is written to a file named after a command instead of piping to the command.
```sh
cat file > tr -d '\''\''
```
```sh
cat file > rm
```
--------------------------------
### Compare String Length Methods in Bash
Source: https://github.com/koalaman/shellcheck/wiki/SC2000
Demonstrates three methods for checking if a string's length is greater than 1: using `wc -c`, `wc -m`, and the preferred `${#variable}` syntax. Use `${#variable}` for a more direct and readable approach.
```bash
#!/usr/bin/env bash
if [ "$( echo "$1" | wc -c )" -gt 1 ]; then
echo "greater than 1"
fi
if [ "$( echo "$1" | wc -m )" -gt 1 ]; then
echo "greater than 1"
fi
if [ "${#1}" -gt 1 ]; then
echo "greater than 1"
fi
```
--------------------------------
### Problematic find -exec usage
Source: https://github.com/koalaman/shellcheck/wiki/SC2150
This example demonstrates an incorrect way to use find -exec with a shell command, which can lead to unexpected behavior.
```sh
find . -type f -exec 'cat {} | wc -l' \;
```
--------------------------------
### Problematic SSH Here Document Expansion
Source: https://github.com/koalaman/shellcheck/wiki/SC2087
This example shows a here document where the EOF token is unquoted, causing client-side expansion of variables like $HOSTNAME.
```sh
ssh host.example.com << EOF
echo "Logged in on $HOSTNAME"
EOF
```