Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mrfyda/codacy-shellcheck
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: codacy/codacy-shellcheck
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Able to merge. These branches can be automatically merged.

Commits on Sep 30, 2019

  1. Add CODEOWNERS

    [skip ci]
    lolgab committed Sep 30, 2019

    Verified

    This commit was signed with the committer’s verified signature.
    drazisil-codecov Joe Becher
    Copy the full SHA
    d84718a View commit details

Commits on Oct 1, 2019

  1. Merge pull request #11 from codacy/add-codeowners

    Add CODEOWNERS
    lolgab authored Oct 1, 2019
    Copy the full SHA
    dcd504c View commit details

Commits on Nov 27, 2019

  1. bump: Update scala to 2.13 and bump sbt plugins and seed

    Signed-off-by: Luís Ferreira <contact@lsferreira.net>
    ljmf00 committed Nov 27, 2019
    Copy the full SHA
    40dd086 View commit details
  2. Add more integration tests: multiple test

    Signed-off-by: Luís Ferreira <contact@lsferreira.net>
    ljmf00 committed Nov 27, 2019
    Copy the full SHA
    6c06a5c View commit details

Commits on Nov 28, 2019

  1. Merge pull request #12 from codacy/luis-ferreira/patch/add-integratio…

    …n-tests
    
    Add integration tests and bump Scala to 2.13
    lolgab authored Nov 28, 2019
    Copy the full SHA
    db1932b View commit details

Commits on Jan 13, 2020

  1. Copy the full SHA
    f55f749 View commit details
  2. Copy the full SHA
    e49ef2a View commit details
  3. Merge pull request #14 from codacy/jose-melo/bump/circleci-orbs

    bump: Bump circleci orbs version and refactor
    josemiguelmelo authored Jan 13, 2020
    Copy the full SHA
    3da9e6c View commit details
  4. Copy the full SHA
    66933b1 View commit details
  5. Merge pull request #15 from codacy/fix/circleci-publish

    fix: Fix docker image tar name on circleci publish
    lolgab authored Jan 13, 2020
    Copy the full SHA
    2022636 View commit details

Commits on Feb 28, 2020

  1. Copy the full SHA
    e660bea View commit details
  2. Copy the full SHA
    23f116d View commit details
  3. Merge pull request #16 from codacy/feat/security-subcategories

    feature: Add security subcategories
    josemiguelmelo authored Feb 28, 2020
    Copy the full SHA
    5ede52f View commit details

Commits on Mar 2, 2020

  1. Copy the full SHA
    c6632cf View commit details
  2. Merge pull request #18 from codacy/codeowners

    clean: Update codeowners
    lolgab authored Mar 2, 2020
    Copy the full SHA
    d8d51bb View commit details

Commits on Mar 12, 2020

  1. fix: Fix Codacy badge link

    Francisco committed Mar 12, 2020
    Copy the full SHA
    d0c08e8 View commit details
  2. Merge pull request #19 from codacy/fix-badge

    fix: Fix Codacy badge link
    lolgab authored Mar 12, 2020
    Copy the full SHA
    bedb86e View commit details

Commits on Aug 4, 2020

  1. Copy the full SHA
    21f436b View commit details

Commits on Aug 5, 2020

  1. Merge pull request #20 from codacy/meta/update-jira-github-actions

    feature: Add Jira GitHub actions from codacy-meta-repo
    Francisco Duarte authored Aug 5, 2020
    Copy the full SHA
    bec1480 View commit details

Commits on Aug 6, 2020

  1. Copy the full SHA
    da63366 View commit details

Commits on Aug 7, 2020

  1. Merge pull request #21 from codacy/meta/update-jira-actions-2020-08-6…

    …_16-00
    
    meta: No longer runs failing worflows for comments on pull requests
    machadoit authored Aug 7, 2020
    Copy the full SHA
    b9d0ba7 View commit details

Commits on Aug 18, 2020

  1. Copy the full SHA
    691ea18 View commit details
  2. Merge pull request #22 from codacy/run-doc-generator

    clean: Remove timeToFix and run doc generator
    lolgab authored Aug 18, 2020
    Copy the full SHA
    b0b6e2f View commit details
  3. Copy the full SHA
    a3a726e View commit details
  4. docs: Run doc generator

    lolgab committed Aug 18, 2020
    Copy the full SHA
    a5fb38b View commit details
  5. Copy the full SHA
    b3dff83 View commit details
  6. bump: Bump sbt to 1.3.13

    lolgab committed Aug 18, 2020
    Copy the full SHA
    9839b88 View commit details

Commits on Aug 19, 2020

  1. fix: Fix wrong copy-paste

    lolgab committed Aug 19, 2020
    Copy the full SHA
    8a878a8 View commit details
  2. Merge pull request #23 from codacy/use-graalvm-native-image

    Use graalvm native image and update ShellCheck to 0.7.1 CY-2625
    lolgab authored Aug 19, 2020
    Copy the full SHA
    3174d2c View commit details

Commits on Aug 28, 2020

  1. Copy the full SHA
    6f1ff44 View commit details
  2. Merge pull request #24 from codacy/fix-sc1056

    fix: Run doc-generator and update SC1056 documentation
    lolgab authored Aug 28, 2020
    Copy the full SHA
    51aa125 View commit details

Commits on Sep 14, 2020

  1. feature: Add enabled property to patterns.json

    Francisco committed Sep 14, 2020
    Copy the full SHA
    881235f View commit details
  2. Merge pull request #25 from codacy/feature/enabled-patterns

    feature: Add enabled property to patterns.json
    Francisco Duarte authored Sep 14, 2020
    Copy the full SHA
    c49cda0 View commit details

Commits on Oct 28, 2020

  1. Copy the full SHA
    e495b16 View commit details
  2. Merge pull request #26 from codacy/bump-gajira

    meta: Bump gajira-comment and gajira-create on Github workflow
    Francisco Duarte authored Oct 28, 2020
    Copy the full SHA
    4a95a7f View commit details

Commits on Jun 8, 2021

  1. bump: Bump plugins test orb CY-4462

    Francisco committed Jun 8, 2021
    Copy the full SHA
    0c1e79d View commit details
  2. fix: Fix native packager build

    Use new native image version instead of abandoned oracle
    Francisco committed Jun 8, 2021
    Copy the full SHA
    f88864e View commit details
  3. Merge pull request #27 from codacy/bump/plugins-test-orb

    bump: Bump plugins test orb CY-4462
    Francisco Duarte authored Jun 8, 2021
    Copy the full SHA
    2a7850d View commit details

Commits on Oct 20, 2021

  1. bump: Update base image CY-5141

    Francisco committed Oct 20, 2021
    Copy the full SHA
    6c336d4 View commit details
  2. Merge pull request #29 from codacy/bump-docker-base-image

    bump: Update base image CY-5141
    machadoit authored Oct 20, 2021
    Copy the full SHA
    881409d View commit details

Commits on Oct 27, 2021

  1. bump: Bump shellcheck version CY-5150

    Francisco committed Oct 27, 2021
    Copy the full SHA
    5bcc1b0 View commit details
  2. Merge pull request #30 from codacy/bump-tool-version

    bump: Bump shellcheck version CY-5150
    Francisco Duarte authored Oct 27, 2021
    Copy the full SHA
    0f0fd78 View commit details

Commits on Jun 30, 2022

  1. Copy the full SHA
    a97946c View commit details
  2. Copy the full SHA
    912bb82 View commit details

Commits on Jul 1, 2022

  1. Copy the full SHA
    f367e43 View commit details
  2. update tests

    stefanvacareanu7 committed Jul 1, 2022
    Copy the full SHA
    69b89ab View commit details
  3. Merge pull request #31 from codacy/Bump_codacy_shellcheck_0.8.0

    Bump codacy shellcheck 0.8.0 CY-6157
    stefanvacareanu7 authored Jul 1, 2022
    Copy the full SHA
    86ba7fa View commit details
  4. clean: Omit "v" from version number

    This makes the syntax of the version reported by this tool consistent
    with all other supported tools.
    
    Reverts a change that was originally introduced in
    codacy#6.
    Paulo Ribeiro committed Jul 1, 2022
    Copy the full SHA
    b5c417e View commit details

Commits on Jul 4, 2022

  1. Merge pull request #32 from codacy/clean/simplify-version-number

    clean: Simplify version number syntax
    Paulo Ribeiro authored Jul 4, 2022
    Copy the full SHA
    22c2ff8 View commit details

Commits on Nov 30, 2022

  1. bump: docker base image

    h314to committed Nov 30, 2022
    Copy the full SHA
    b5d9124 View commit details
Showing 564 changed files with 13,679 additions and 4,897 deletions.
57 changes: 19 additions & 38 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
version: 2.1

orbs:
codacy: codacy/base@0.3.3
codacy: codacy/base@10.2.2
codacy_plugins_test: codacy/plugins-test@1.1.1

workflows:
version: 2
@@ -10,49 +11,29 @@ workflows:
- codacy/checkout_and_version:
write_sbt_version: true
- codacy/sbt:
name: populate_cache
name: publish_docker_local
cmd: |
git clone --depth 1 git://github.com/codacy/codacy-plugins-test.git codacy-plugins-test
sbt ";set scalafmtUseIvy in ThisBuild := false;update"
(cd codacy-plugins-test && sbt update)
sbt "scalafmt::test;
test:scalafmt::test;
sbt:scalafmt::test;
universal:stage;
graalvm-native-image:packageBin"
docker build -t $CIRCLE_PROJECT_REPONAME:latest .
docker save --output docker-image.tar $CIRCLE_PROJECT_REPONAME:latest
persist_to_workspace: true
requires:
- codacy/checkout_and_version
- codacy/sbt:
name: check_fmt
cmd: sbt ";scalafmt::test;test:scalafmt::test;sbt:scalafmt::test"
requires:
- populate_cache
- codacy/sbt:
name: compile
cmd: sbt compile
requires:
- populate_cache

- codacy/sbt:
name: test_patterns
persist_to_workspace: true
cmd: |
docker build -t codacy/alpine-jre-shellcheck -f Dockerfile .
sbt 'set version in Docker := "latest"' "set name := \"$CIRCLE_PROJECT_REPONAME\"" docker:publishLocal
git clone --depth 1 git://github.com/codacy/codacy-plugins-test.git codacy-plugins-test
(cd codacy-plugins-test &&
sbt -Dcodacy.tests.ignore.descriptions=true "runMain codacy.plugins.DockerTest json $CIRCLE_PROJECT_REPONAME:latest"
sbt -Dcodacy.tests.ignore.descriptions=true "runMain codacy.plugins.DockerTest pattern $CIRCLE_PROJECT_REPONAME:latest")
docker save --output workspace_docker.tar codacy/alpine-jre-shellcheck $CIRCLE_PROJECT_REPONAME:latest
- codacy_plugins_test/run:
name: plugins_test
run_multiple_tests: true
requires:
- compile
- codacy/sbt:
name: publish_dockerhub
- publish_docker_local

- codacy/publish_docker:
context: CodacyDocker
cmd: |
docker load --input workspace_docker.tar
docker login -u $DOCKER_USER -p $DOCKER_PASS
docker tag $CIRCLE_PROJECT_REPONAME codacy/$CIRCLE_PROJECT_REPONAME:$(cat .version)
docker tag $CIRCLE_PROJECT_REPONAME codacy/$CIRCLE_PROJECT_REPONAME:latest
docker push codacy/$CIRCLE_PROJECT_REPONAME:$(cat .version)
docker push codacy/$CIRCLE_PROJECT_REPONAME:latest
requires:
- test_patterns
- plugins_test
filters:
branches:
only:
@@ -61,7 +42,7 @@ workflows:
name: tag_version
context: CodacyAWS
requires:
- publish_dockerhub
- codacy/publish_docker
filters:
branches:
only:
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Ignore everything
**

# Allow files and directories
!/target/graalvm-native-image/codacy-shellcheck
!/target/universal/stage/
!/docs

# Ignore unnecessary files inside allowed directories
# This should go after the allowed directories
**/.DS_Store
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @codacy/toss
97 changes: 97 additions & 0 deletions .github/workflows/comment_issue.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: Comment issue on Jira

on:
issue_comment:
types: [created]

jobs:
jira:
env:
JIRA_CREATE_COMMENT_AUTO: ${{ secrets.JIRA_CREATE_COMMENT_AUTO }}
runs-on: ubuntu-latest
steps:

- name: Start workflow if JIRA_CREATE_COMMENT_AUTO is enabled
if: env.JIRA_CREATE_COMMENT_AUTO == 'true'
run: echo "Starting workflow"

- name: Check GitHub Issue type
if: env.JIRA_CREATE_COMMENT_AUTO == 'true'
id: github_issue_type
uses: actions/github-script@v2.0.0
with:
result-encoding: string
script: |
// An Issue can be a pull request, you can identify pull requests by the pull_request key
const pullRequest = ${{ toJson(github.event.issue.pull_request) }}
if(pullRequest) {
return "pull-request"
} else {
return "issue"
}
- name: Check if GitHub Issue has JIRA_ISSUE_LABEL
if: env.JIRA_CREATE_COMMENT_AUTO == 'true'
id: github_issue_has_jira_issue_label
uses: actions/github-script@v2.0.0
env:
JIRA_ISSUE_LABEL: ${{ secrets.JIRA_ISSUE_LABEL }}
with:
result-encoding: string
script: |
const labels = ${{ toJson(github.event.issue.labels) }}
if(labels.find(label => label.name == process.env.JIRA_ISSUE_LABEL)) {
return "true"
} else {
return "false"
}
- name: Continue workflow only for Issues (not Pull Requests) tagged with JIRA_ISSUE_LABEL
if: env.JIRA_CREATE_COMMENT_AUTO == 'true' && env.GITHUB_ISSUE_TYPE == 'issue' && env.GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL == 'true'
env:
GITHUB_ISSUE_TYPE: ${{ steps.github_issue_type.outputs.result }}
GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL: ${{ steps.github_issue_has_jira_issue_label.outputs.result }}
run: echo "GitHub Issue is tracked on Jira, eligilbe to be commented"

- name: Jira Login
if: env.JIRA_CREATE_COMMENT_AUTO == 'true' && env.GITHUB_ISSUE_TYPE == 'issue' && env.GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL == 'true'
id: login
uses: atlassian/gajira-login@v2.0.0
env:
GITHUB_ISSUE_TYPE: ${{ steps.github_issue_type.outputs.result }}
GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL: ${{ steps.github_issue_has_jira_issue_label.outputs.result }}
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}

- name: Extract Jira number
if: env.JIRA_CREATE_COMMENT_AUTO == 'true' && env.GITHUB_ISSUE_TYPE == 'issue' && env.GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL == 'true'
id: extract_jira_number
uses: actions/github-script@v2.0.0
env:
GITHUB_ISSUE_TYPE: ${{ steps.github_issue_type.outputs.result }}
GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL: ${{ steps.github_issue_has_jira_issue_label.outputs.result }}
JIRA_PROJECT: ${{ secrets.JIRA_PROJECT }}
GITHUB_TITLE: ${{ github.event.issue.title }}
with:
script: |
const jiraTaskRegex = new RegExp(`\\\[(${process.env.JIRA_PROJECT}-[0-9]+?)\\\]`)
return process.env.GITHUB_TITLE.match(jiraTaskRegex)[1]
result-encoding: string

- name: Jira Add comment on issue
if: env.JIRA_CREATE_COMMENT_AUTO == 'true' && env.GITHUB_ISSUE_TYPE == 'issue' && env.GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL == 'true'
id: add_comment_jira_issue
uses: atlassian/gajira-comment@v2.0.2
env:
GITHUB_ISSUE_TYPE: ${{ steps.github_issue_type.outputs.result }}
GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL: ${{ steps.github_issue_has_jira_issue_label.outputs.result }}
with:
issue: ${{ steps.extract_jira_number.outputs.result }}
comment: |
GitHub Comment : ${{ github.event.comment.user.login }}
{quote}${{ github.event.comment.body }}{quote}
----
{panel}
_[Github permalink |${{ github.event.comment.html_url }}]_
{panel}
90 changes: 90 additions & 0 deletions .github/workflows/create_issue.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Create issue on Jira

on:
issues:
types: [opened]

jobs:
jira:
env:
JIRA_CREATE_ISSUE_AUTO: ${{ secrets.JIRA_CREATE_ISSUE_AUTO }}
runs-on: ubuntu-latest
steps:

- name: Start workflow if JIRA_CREATE_ISSUE_AUTO is enabled
if: env.JIRA_CREATE_ISSUE_AUTO == 'true'
run: echo "Starting workflow"

- name: Jira Login
if: env.JIRA_CREATE_ISSUE_AUTO == 'true'
id: login
uses: atlassian/gajira-login@v2.0.0
env:
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}

- name: Jira Create issue
if: env.JIRA_CREATE_ISSUE_AUTO == 'true'
id: create_jira_issue
uses: atlassian/gajira-create@v2.0.1
with:
project: ${{ secrets.JIRA_PROJECT }}
issuetype: ${{ secrets.JIRA_ISSUE_TYPE }}
summary: "[GH#${{ github.event.issue.number }}] ${{ github.event.issue.title }}"
description: |
${{ github.event.issue.body }}
----
{panel}
_[Github permalink |${{ github.event.issue.html_url }}]_
{panel}
- name: Update Jira issue if JIRA_UPDATE_ISSUE_BODY is defined
if: env.JIRA_CREATE_ISSUE_AUTO == 'true' && env.JIRA_UPDATE_ISSUE_BODY != ''
env:
JIRA_UPDATE_ISSUE_BODY: ${{ secrets.JIRA_UPDATE_ISSUE_BODY }}
run: >
curl
-u ${{ secrets.JIRA_USER_EMAIL }}:${{ secrets.JIRA_API_TOKEN }}
-X PUT
-H 'Content-Type: application/json'
-d '${{ env.JIRA_UPDATE_ISSUE_BODY }}'
${{ secrets.JIRA_BASE_URL }}/rest/api/2/issue/${{ steps.create_jira_issue.outputs.issue }}
- name: Update GitHub issue
if: env.JIRA_CREATE_ISSUE_AUTO == 'true'
uses: actions/github-script@v2.0.0
env:
JIRA_ISSUE_NUMBER: ${{ steps.create_jira_issue.outputs.issue }}
GITHUB_ORIGINAL_TITLE: ${{ github.event.issue.title }}
JIRA_ISSUE_LABEL: ${{ secrets.JIRA_ISSUE_LABEL }}
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
const newTitle = `[${process.env.JIRA_ISSUE_NUMBER}] ${process.env.GITHUB_ORIGINAL_TITLE}`
github.issues.update({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
title: newTitle
})
github.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: [process.env.JIRA_ISSUE_LABEL]
})
- name: Add comment after sync
if: env.JIRA_CREATE_ISSUE_AUTO == 'true'
uses: actions/github-script@v2.0.0
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Internal ticket created : [${{ steps.create_jira_issue.outputs.issue }}](${{ secrets.JIRA_BASE_URL }}/browse/${{ steps.create_jira_issue.outputs.issue }})'
})
82 changes: 82 additions & 0 deletions .github/workflows/create_issue_on_label.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Create issue on Jira when labeled with JIRA_ISSUE_LABEL

on:
issues:
types: [labeled]

jobs:
jira:
env:
JIRA_ISSUE_LABEL: ${{ secrets.JIRA_ISSUE_LABEL }}
runs-on: ubuntu-latest
steps:

- name: Start workflow if GitHub issue is tagged with JIRA_ISSUE_LABEL
if: github.event.label.name == env.JIRA_ISSUE_LABEL
run: echo "Starting workflow"

- name: Jira Login
if: github.event.label.name == env.JIRA_ISSUE_LABEL
id: login
uses: atlassian/gajira-login@v2.0.0
env:
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}

- name: Jira Create issue
if: github.event.label.name == env.JIRA_ISSUE_LABEL
id: create_jira_issue
uses: atlassian/gajira-create@v2.0.1
with:
project: ${{ secrets.JIRA_PROJECT }}
issuetype: ${{ secrets.JIRA_ISSUE_TYPE }}
summary: "[GH#${{ github.event.issue.number }}] ${{ github.event.issue.title }}"
description: |
${{ github.event.issue.body }}
----
{panel}
_[Github permalink |${{ github.event.issue.html_url }}]_
{panel}
- name: Update Jira issue if JIRA_UPDATE_ISSUE_BODY is defined
if: github.event.label.name == env.JIRA_ISSUE_LABEL && env.JIRA_UPDATE_ISSUE_BODY != ''
env:
JIRA_UPDATE_ISSUE_BODY: ${{ secrets.JIRA_UPDATE_ISSUE_BODY }}
run: >
curl
-u ${{ secrets.JIRA_USER_EMAIL }}:${{ secrets.JIRA_API_TOKEN }}
-X PUT
-H 'Content-Type: application/json'
-d '${{ env.JIRA_UPDATE_ISSUE_BODY }}'
${{ secrets.JIRA_BASE_URL }}/rest/api/2/issue/${{ steps.create_jira_issue.outputs.issue }}
- name: Change Title
if: github.event.label.name == env.JIRA_ISSUE_LABEL
uses: actions/github-script@v2.0.0
env:
JIRA_ISSUE_NUMBER: ${{ steps.create_jira_issue.outputs.issue }}
GITHUB_ORIGINAL_TITLE: ${{ github.event.issue.title }}
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
const newTitle = `[${process.env.JIRA_ISSUE_NUMBER}] ${process.env.GITHUB_ORIGINAL_TITLE}`
github.issues.update({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
title: newTitle
})
- name: Add comment after sync
if: github.event.label.name == env.JIRA_ISSUE_LABEL
uses: actions/github-script@v2.0.0
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Internal ticket created : [${{ steps.create_jira_issue.outputs.issue }}](${{ secrets.JIRA_BASE_URL }}/browse/${{ steps.create_jira_issue.outputs.issue }})'
})
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -8,5 +8,6 @@
.metals
.bloop
.DS_Store
docs/shellcheck
docs/shellcheck.wiki
doc-generator/shellcheck
doc-generator/shellcheck.wiki
.vscode/
36 changes: 31 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
FROM koalaman/shellcheck-alpine:v0.7.0 AS build
FROM alpine:3.17.3 as base

FROM openjdk:8-jre-alpine
LABEL maintainer="Rafael Cortes <mrfyda@gmail.com>"
COPY --from=build /bin/shellcheck /bin
CMD shellcheck
ARG SHELLCHECK_VERSION=0.9.0

RUN apk add --no-cache bash

RUN export EXTRACTED_DIR_NAME=shellcheck-v$SHELLCHECK_VERSION && \
export ARCHIVE_NAME=$EXTRACTED_DIR_NAME.linux.x86_64.tar.xz && \
wget https://github.com/koalaman/shellcheck/releases/download/v$SHELLCHECK_VERSION/$ARCHIVE_NAME && \
tar -xf $ARCHIVE_NAME && \
mv $EXTRACTED_DIR_NAME/shellcheck /usr/bin && \
rm -rf $EXTRACTED_DIR_NAME $ARCHIVE_NAME

FROM base as dev

RUN apk add --no-cache openjdk11
COPY docs /docs
RUN adduser --uid 2004 --disabled-password --gecos "" docker
COPY target/universal/stage/ /workdir/
RUN chmod +x /workdir/bin/codacy-shellcheck
USER docker
WORKDIR /workdir
ENTRYPOINT ["bin/codacy-shellcheck"]

FROM base

COPY docs /docs
RUN adduser --uid 2004 --disabled-password --gecos "" docker
COPY target/graalvm-native-image/codacy-shellcheck /workdir/
USER docker
WORKDIR /workdir
ENTRYPOINT ["/workdir/codacy-shellcheck"]
26 changes: 16 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/e6e9a17f8190438e83874c1b3f7cb62f)](https://www.codacy.com/app/Codacy/codacy-shellcheck?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=codacy/codacy-shellcheck&amp;utm_campaign=Badge_Grade)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/e6e9a17f8190438e83874c1b3f7cb62f)](https://www.codacy.com/gh/codacy/codacy-shellcheck?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=codacy/codacy-shellcheck&amp;utm_campaign=Badge_Grade)
[![Build Status](https://circleci.com/gh/codacy/codacy-shellcheck.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/codacy/codacy-shellcheck)

# Codacy ShellCheck

Create the docker: `sbt docker:publishLocal`
Create the docker:

```bash
sbt universal:stage graalvm-native-image:packageBin
docker build -t codacy-shellcheck .
```

The docker is supposed to be run with the following command:

@@ -21,20 +26,21 @@ and $srcDir must contain a valid `.codacy.json` configuration

## Test

Follow the instructions at [codacy-plugins-test](https://github.com/codacy/codacy-plugins-test/blob/master/README.md#test-definition)

## Generating the documentation

1. Update the version tag in `Dockerfile` and run:
For a faster development loop you can create a Docker image based on the JVM instead of creating a native-image:

```bash
docker build -t codacy/alpine-jre-shellcheck -f Dockerfile .
sbt universal:stage
docker build -t codacy-shellcheck --target dev .
```

2. Update the `VERSION` variable in `generate.sh` and run:
Follow the instructions at [codacy-plugins-test](https://github.com/codacy/codacy-plugins-test/blob/master/README.md#test-definition)

## Generating the documentation

1. Update the `VERSION` variable in `generate.sh` and run:

```bash
cd docs
cd doc-generator
./generate.sh
```

58 changes: 15 additions & 43 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,50 +1,22 @@
import com.typesafe.sbt.packager.docker.{Cmd, ExecCmd}

organization := "codacy"
organization := "com.codacy"

name := "codacy-shellcheck"

version := "1.0.0-SNAPSHOT"

val languageVersion = "2.12.9"

scalaVersion := languageVersion

resolvers ++= Seq(
"Sonatype OSS Snapshots".at("https://oss.sonatype.org/content/repositories/releases"),
"Typesafe Repo".at("http://repo.typesafe.com/typesafe/releases/")
)

libraryDependencies ++= Seq("com.codacy" %% "codacy-engine-scala-seed" % "3.0.296" withSources ())

enablePlugins(AshScriptPlugin)
scalaVersion := "2.13.3"

enablePlugins(DockerPlugin)
libraryDependencies += "com.codacy" %% "codacy-engine-scala-seed" % "4.1.1"

version in Docker := "1.0"
enablePlugins(GraalVMNativeImagePlugin)

mappings in Universal ++= {
(resourceDirectory in Compile) map { (resourceDir: File) =>
val src = resourceDir / "docs"
val dest = "/docs"
val graalVersion = "java11-21.1.0"

for {
path <- src.allPaths.get if !path.isDirectory
} yield path -> path.toString.replaceFirst(src.toString, dest)
}
}.value

val dockerUser = "docker"
val dockerGroup = "docker"

daemonUser in Docker := dockerUser

daemonGroup in Docker := dockerGroup

dockerBaseImage := s"codacy/alpine-jre-shellcheck"

dockerCommands := dockerCommands.value.flatMap {
case cmd @ Cmd("ADD", _) =>
List(Cmd("RUN", s"adduser -u 2004 -D $dockerUser"), cmd, Cmd("RUN", "mv /opt/docker/docs /docs"))
case other => List(other)
}
graalVMNativeImageGraalVersion := Some(graalVersion)
graalVMNativeImageOptions ++= Seq(
"-O1",
"-H:+ReportExceptionStackTraces",
"--no-fallback",
"--no-server",
"--initialize-at-build-time",
"--report-unsupported-elements-at-runtime",
"--static"
)
130 changes: 130 additions & 0 deletions doc-generator/categories.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
[
{
"patternId": "SC2001",
"category": "CodeStyle"
},
{
"patternId": "SC2002",
"category": "Performance"
},
{
"patternId": "SC2003",
"category": "CodeStyle"
},
{
"patternId": "SC2004",
"category": "CodeStyle"
},
{
"patternId": "SC2006",
"category": "CodeStyle"
},
{
"patternId": "SC2008",
"category": "ErrorProne"
},
{
"patternId": "SC2009",
"category": "BestPractice"
},
{
"patternId": "SC2010",
"category": "BestPractice"
},
{
"patternId": "SC2012",
"category": "BestPractice"
},
{
"patternId": "SC2013",
"category": "BestPractice"
},
{
"patternId": "SC2014",
"category": "BestPractice"
},
{
"patternId": "SC2015",
"category": "ErrorProne"
},
{
"patternId": "SC2016",
"category": "CodeStyle"
},
{
"patternId": "SC2017",
"category": "BestPractice"
},
{
"patternId": "SC2020",
"category": "ErrorProne"
},
{
"patternId": "SC2022",
"category": "ErrorProne"
},
{
"patternId": "SC2024",
"category": "ErrorProne"
},
{
"patternId": "SC2025",
"category": "CodeStyle"
},
{
"patternId": "SC2026",
"category": "ErrorProne"
},
{
"patternId": "SC2027",
"category": "ErrorProne"
},
{
"patternId": "SC2028",
"category": "ErrorProne"
},
{
"patternId": "SC2029",
"category": "ErrorProne"
},
{
"patternId": "SC2031",
"category": "ErrorProne"
},
{
"patternId": "SC2033",
"category": "ErrorProne"
},
{
"patternId": "SC2034",
"category": "ErrorProne"
},
{
"patternId": "SC2036",
"category": "ErrorProne"
},
{
"patternId": "SC2148",
"category": "ErrorProne"
},
{
"patternId": "SC2092",
"category": "Security",
"subcategory": "CommandInjection"
},
{
"patternId": "SC2091",
"category": "Security",
"subcategory": "CommandInjection"
},
{
"patternId": "SC2223",
"category": "Security",
"subcategory": "DoS"
},
{
"patternId": "SC2156",
"category": "Security",
"subcategory": "CommandInjection"
}
]
24 changes: 24 additions & 0 deletions doc-generator/defaults.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[
"SC2001",
"SC2002",
"SC2003",
"SC2004",
"SC2006",
"SC2015",
"SC2016",
"SC2020",
"SC2022",
"SC2024",
"SC2025",
"SC2026",
"SC2027",
"SC2028",
"SC2029",
"SC2031",
"SC2033",
"SC2034",
"SC2035",
"SC2036",
"SC2086",
"SC2148"
]
18 changes: 12 additions & 6 deletions docs/generate.sh → doc-generator/generate.sh
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#!/bin/bash

SCRIPT_HOME="$( cd "$( dirname "$0" )" && pwd )"
DOCS_HOME="${SCRIPT_HOME}/../src/main/resources/docs"
DOCS_HOME="${SCRIPT_HOME}/../docs"
DESCRIPTION_HOME="${DOCS_HOME}/description"
VERSION="v0.7.0"
VERSION="v0.9.0"

rm -rf shellcheck shellcheck.wiki
git clone -b $VERSION --single-branch --depth 1 https://github.com/koalaman/shellcheck.git
git clone -b v$VERSION --single-branch --depth 1 https://github.com/koalaman/shellcheck.git
git clone https://github.com/koalaman/shellcheck.wiki.git

cd shellcheck.wiki
@@ -29,7 +29,9 @@ for f in SC*; do
internal_id=`echo $pattern_id | grep -o '[0-9]\+'`
category=`cat $SCRIPT_HOME/categories.json | jq -SM ".[] | select(.patternId==\"$pattern_id\") | .category" | tr -d '"'`
category=${category:=CodeStyle}
subcategory=`cat $SCRIPT_HOME/categories.json | jq -SM ".[] | select((.patternId==\"$pattern_id\") and .category==\"Security\") | .subcategory" | tr -d '"'`
severity=`grep -hR $internal_id ../shellcheck`
enabled=`cat $SCRIPT_HOME/defaults.json | jq "contains([\"$pattern_id\"])"`
case $severity in
*"err"*) level="Error" ;;
*"ErrorC"*) level="Error" ;;
@@ -39,17 +41,21 @@ for f in SC*; do
*"InfoC"*) level="Info" ;;
*) level="Info" ;;
esac
patterns+=$(jq -cMn --arg patternId "$pattern_id" --arg level "$level" --arg category "$category" '{"patternId": $patternId, "level": $level, "category": $category}')
if [ "$subcategory" != "" ]; then
patterns+=$(jq -cMn --arg patternId "$pattern_id" --arg level "$level" --arg category "$category" --arg subcategory "$subcategory" --argjson enabled $enabled '{"patternId": $patternId, "level": $level, "category": $category, "subcategory": $subcategory, "enabled": $enabled}')
else
patterns+=$(jq -cMn --arg patternId "$pattern_id" --arg level "$level" --arg category "$category" --argjson enabled $enabled '{"patternId": $patternId, "level": $level, "category": $category, "enabled": $enabled}')
fi
done

jq -Mn --arg version "$VERSION" --argjson patterns "[$patterns]" '{"name": "shellcheck", "version": $version, "patterns": $patterns}' > "${DOCS_HOME}/patterns.json"

# description.json
for f in SC*; do
pattern_id=`echo $f | awk '{print substr($0,0,6)}'`
title=$(head -n 1 $f | sed 's/^#* *//')
title=$(head -n 1 $f | sed -e 's/^[[:space:]]*//' | sed 's/^#* *//')
[ -n "$descriptions" ] && descriptions+=","
descriptions+=$(jq -cMn --arg patternId "$pattern_id" --arg title "$title" '{"patternId": $patternId, "title": $title, "description": $title, "timeToFix": 5}')
descriptions+=$(jq -cMn --arg patternId "$pattern_id" --arg title "$title" '{"patternId": $patternId, "title": $title, "description": $title}')
done

jq -Mn --argjson descriptions "[$descriptions]" '$descriptions' > "${DESCRIPTION_HOME}/description.json"
110 changes: 0 additions & 110 deletions docs/categories.json

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# $ is not used specially and should therefore be escaped.
# `$` is not used specially and should therefore be escaped.

### Problematic code:

@@ -20,5 +20,6 @@ echo "\$"

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

Removed in [v0.3.3 - 2014-05-29](https://github.com/koalaman/shellcheck/blob/2e5c56b27034492134be1538c1e1e6a533ca791a/CHANGELOG.md#removed-1)
[Source](https://github.com/koalaman/shellcheck/wiki/SC1000)

Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@ If you wanted it to expand to something, rewrite the expression to use `printf`

### Exceptions

None. ShellCheck (as of 2017-07-03, commit 31bb02d6) will not warn when the first letter of a command is unnecessarily escaped, as this is frequently used to suppress aliases interactively.
None. ShellCheck (as of [2017-07-03](https://github.com/koalaman/shellcheck/commit/31bb02d6b794f248f732643d744f63bec615b1f7), commit [`31bb02d6`](https://github.com/koalaman/shellcheck/commit/31bb02d6b794f248f732643d744f63bec615b1f7)) will not warn when the first letter of a command is unnecessarily escaped, as this is frequently used to suppress aliases interactively.

[Source](https://github.com/koalaman/shellcheck/wiki/SC1001)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Want to escape a single quote? echo 'This is how it'\\''s done'.
## Want to escape a single quote? `echo 'This is how it'\''s done'`.

(Note: in v0.4.6, the error message was accidentally missing the backslash)

@@ -17,14 +17,14 @@ echo 'This is how it'\''s done'.

### Rationale

In POSIX shell, the shell cares about nothing but another single quote to terminate the quoted segment. Not even backslashes are interpreted.
In POSIX shell, the shell cares about nothing but another single-quote to terminate the quoted segment. Not even backslashes are interpreted.

[POSIX.1 Shell Command Language § 2.2.2 Single Quotes](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02_02):

> Enclosing characters in single-quotes ( `''` ) shall preserve the literal value of each character within the single-quotes. A single-quote cannot occur within single-quotes.
### Exceptions
If you want your single quoted string to end in a backslash, you can rewrite as `'string'\\` or [[ignore]] this warning.
If you want your single-quoted string to end in a backslash, you can rewrite as `'string'\\` or [[ignore]] this warning.

[Source](https://github.com/koalaman/shellcheck/wiki/SC1003)

Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## This backslash+linefeed is literal. Break outside single quotes if you just want to break the line.

(This warning was retired after 0.7.2 due to low signal-to-noise ratio)

### Problematic code:

```sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Remove space after = if trying to assign a value (or for empty string, use var='' ... ).
# Remove space after `=` if trying to assign a value (or for empty string, use `var=''` ... ).

### Problematic code:

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

@@ -15,7 +15,7 @@ LANGUAGE= nl
### Correct code:

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

File renamed without changes.
File renamed without changes.
40 changes: 40 additions & 0 deletions docs/description/SC1010.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## Use semicolon or linefeed before `done` (or quote to make it literal).

(or `do` `then`, `fi`, `esac`)

### Problematic code:

```sh
for f in *; do echo "$f" done
```
or

```sh
echo $f is done
```

### Correct code:

```sh
for f in *; do echo "$f"; done
```

or

```sh
echo "$f is done"
```


### Rationale:

ShellCheck found a keyword like `done`, `then`, `fi`, `esac`, etc used as the argument of a command. This means that the shell will interpret it as a literal string rather than a shell keyword. To be interpreted as a keyword, it must be the first word in the line (i.e. after `;`, `&` or a linefeed).

In the example, `echo "$f" done` is the same as `echo "$f" "done"`, and the `done` does not terminate the loop. This is fixed by terminating the `echo` command with a `;` so that the `done` is the first word in the next line.

### Exceptions

If you're intentionally using `done` as a literal, you can quote it to make this clear to ShellCheck (and also human readers), e.g. instead of `echo Task is done`, use `echo "Task is done"`. This makes no difference to the shell, but it will silence this warning.

[Source](https://github.com/koalaman/shellcheck/wiki/SC1010)

Original file line number Diff line number Diff line change
@@ -17,12 +17,13 @@ echo "Nothing so needs reforming as other people's habits."
```
### Rationale:

When writing a string in single quotes, you have to make sure that any apostrophes in the text don't accidentally terminate the single quoted string prematurely.
When writing a string in single-quotes, you have to make sure that any apostrophes in the text don't accidentally terminate the single-quoted string prematurely.

Escape them properly (see the correct code) or switch quotes to avoid the problem.

### Exceptions:

None.

[Source](https://github.com/koalaman/shellcheck/wiki/SC1011)

Original file line number Diff line number Diff line change
@@ -22,14 +22,16 @@ var="$(printf 'foo\tbar')" # Equivalent alternative
```

or

```sh
# Literal, quoted linefeed
line="foo
bar"
```

### Rationale:

ShellCheck has found a `\t`, `\n` or `\r` in a context where they just become regular letter `t`, `n` or `r`. Most likely, it was intended as a tab, linefeed or carriage return.
ShellCheck has found a `\t`, `\n` or `\r` in a context where they just become regular letters `t`, `n` or `r`. Most likely, it was intended as a tab, linefeed or carriage return.

To generate such characters (plus other less common ones including `\a`, `\f` and octal escapes) , use `printf` as in the example. The exception is for linefeeds that would be stripped by command substitution; in these cases, use a literal quoted linefeed instead.

@@ -42,5 +44,6 @@ None.
### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!

[Source](https://github.com/koalaman/shellcheck/wiki/SC1012)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Use 'if cmd; then ..' to check exit code, or 'if [ "$(cmd)" = .. ]' to check output.
## Use `if cmd; then ..` to check exit code, or `if [ "$(cmd)" = .. ]` to check output.

### Problematic code:

@@ -28,7 +28,7 @@ If you want to check the exit status of a certain command, use that command dire

If you want to check the output of a command, use `"$(..)"` to get its output, and then use `test` or `[`/`[[` to do a string comparison:

```
```sh
# Check output of `whoami` against the string `root`
if [ "$(whoami)" = "root" ]
then
@@ -45,6 +45,7 @@ None.
### Related resources:

* [How do I use a file grep comparison inside a bash if/else statement?](https://stackoverflow.com/questions/2480584/how-do-i-use-a-file-grep-comparison-inside-a-bash-if-else-statement)
* Bash Pitfalls: [ if [grep foo myfile] ](https://mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D)
* [Bash Pitfalls: `if [grep foo myfile]`](https://mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D)

[Source](https://github.com/koalaman/shellcheck/wiki/SC1014)

File renamed without changes.
File renamed without changes.
43 changes: 43 additions & 0 deletions docs/description/SC1017.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
## Literal carriage return. Run script through `tr -d '\r'` .

### Problematic code:

```console
$ cat -v myscript
#!/bin/sh^M
echo "Hello World"^M
```

### Correct code:

```console
$ cat -v myscript
#!/bin/sh
echo "Hello World"
```

### Rationale:

The script uses Windows/MS-DOS style `\r\n` line terminators instead of Unix-style `\n` terminators. The additional `\r` aka `^M` aka carriage return characters will be treated literally, and results in all sorts strange bugs and messages.

You can verify this with `cat -v yourfile` and see whether or not each line ends with a `^M`. To delete them, open the file in your editor and save the file as "Unix", "Unix/macOS Format", `:set ff=unix` or similar if it supports it.

If you don't know how to get your editor to save a file with Unix line terminators, you can use `tr`:

```sh
tr -d '\r' < badscript > goodscript
```

This will read a script `badscript` with possible carriage returns, and write `goodscript` without them.

### Exceptions:

None

### Related resources:

* [BashFaq: How do I convert a file from MS-DOS format to Unix format (remove CRs from CR-LF line terminators)?](https://mywiki.wooledge.org/BashFAQ/052)
* [StackOverflow: Are shell-scripts sensitive to encoding and line-endings?](https://stackoverflow.com/questions/39527571/are-shell-scripts-sensitive-to-encoding-and-line-endings)

[Source](https://github.com/koalaman/shellcheck/wiki/SC1017)

16 changes: 16 additions & 0 deletions docs/description/SC1018.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# This is a unicode non-breaking space. Delete it and retype as space.

You copy-pasted some code, probably from a blog or web site, which for formatting reasons contained Unicode no-break spaces or Unicode zero-width spaces instead of regular spaces or in words.

To humans, a zero-width space is invisible and a non-breaking space is indistinguishable from a regular space, but the shell does not agree.

If you have just a few, delete the indicated space/word and retype it. If you have tons, do a search-and-replace in your editor (copy-paste an offending space into the search field, and type a regular space into the replace field), or use the following command to remove them:

```sh
sed -e $'s/\xC2\xA0/ /g' -e $'s/\xE2\x80\x8b//g' -i yourfile
```

On macOS, a non-breaking space can be inserted into most programs by holding <kbd>⌥ Option</kbd>+<kbd>Space</kbd>.

[Source](https://github.com/koalaman/shellcheck/wiki/SC1018)

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
## You need a space before the if single then "]" else "]]"
## You need a space before the `]` or `]]`

### Problematic code:

```
```sh
if [ "$STUFF" = ""]; then
```
### Correct code:
```
```sh
if [ "$STUFF" = "" ]; then
```
### Rationale:
Bourne shells are very whitespace sensitive. Adding or removing spaces can drastically alter the meaning of a script. In these cases, ShellCheck has noticed that you're missing a space at the position indicated.
### Exceptions
none.
None.
### Ignore
```
```sh
# shellcheck disable=SC1020
if [ "$STUFF" = ""]; then
...
```
[Source](https://github.com/koalaman/shellcheck/wiki/SC1020)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## If grouping expressions inside [[..]], use ( .. ).
## If grouping expressions inside `[[..]]`, use `( .. )`.

### Problematic code:

26 changes: 26 additions & 0 deletions docs/description/SC1027.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
## Expected another argument for this operator.

### Problematic code:

```sh
[ $a -ne ]
```

### Correct code:

```sh
[ $a -ne $b ]
```
### Rationale:

ShellCheck found a `test` operator without an operand. This could be a copy-paste fail, bad linebreak, or trying to use `<>` instead of `!=` or `-ne`.

### Exceptions:

None.

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1027)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## In [..] you have to escape \\( \\) or preferably combine [..] expressions.
## In `[..]` you have to escape `\( \)` or preferably combine `[..]` expressions.

### Problematic code:

File renamed without changes.
46 changes: 46 additions & 0 deletions docs/description/SC1033.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## Test expression was opened with double `[[` but closed with single `]`. Make sure they match.

(or [[SC1034]] for vice versa)

### Problematic code:

```sh
[[ -z "$var" ]
```

### Correct code:

```sh
[[ -z "$var" ]]
```

### Rationale:

ShellCheck found a test expression `[ ... ]` (POSIX) or `[[ ... ]]` (ksh/bash), but where the opening and closing brackets did not match (i.e. `[[ .. ]` or `[ .. ]]`). The brackets need to match up to work.

Note in particular that `[..]` do *not* work like parentheses in other languages. You can not do:

```sh
# Invalid
[[ x ] || [ y ]]
```
You would instead use two separate test expressions joined by `||`:

```sh
# Valid basic test expressions (sh/bash/ksh)
[ x ] || [ y ]

# Valid extended test expressions (bash/ksh)
[[ x ]] || [[ y ]]
```

### Exceptions:

None

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!

[Source](https://github.com/koalaman/shellcheck/wiki/SC1033)

4 changes: 4 additions & 0 deletions docs/description/SC1034.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## Test expression was opened with double `[` but closed with single `]]`. Make sure they match.
See similar error [[SC1033]]
[Source](https://github.com/koalaman/shellcheck/wiki/SC1034)

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -30,14 +30,17 @@ Determine what you intended the parenthesis to do and rewrite accordingly. Commo

Bash allows some parentheses as part of assignment-like tokens to certain commands, including `export` and `eval`. This is a workaround in Bash to allow commands that normally would not be valid:

eval foo=(bar) # Valid command
echo foo=(bar) # Invalid syntax
f=foo; eval $f=(bar) # Also invalid
```sh
eval foo=(bar) # Valid command
echo foo=(bar) # Invalid syntax
f=foo; eval $f=(bar) # Also invalid
```

In these cases, please quote the command, such as `eval "foo=(bar)". This does not change the behavior, but stops relying on bash specific parsing quirks.
In these cases, please quote the command, such as `eval "foo=(bar)"`. This does not change the behavior, but stops relying on Bash-specific parsing quirks.

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!

[Source](https://github.com/koalaman/shellcheck/wiki/SC1036)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Braces are required for positionals over 9, e.g. ${10}.
## Braces are required for positionals over 9, e.g. `${10}`.

### Problematic code:

@@ -22,7 +22,7 @@ Curly braces are needed to tell the shell that both digits are part of the param

### Exceptions

If you wanted the trailing digits to be literal, `${1}0` will make this clear to both humans and shellcheck.
If you wanted the trailing digits to be literal, `${1}0` will make this clear to both humans and ShellCheck.

In `dash`, `$10` is ([wrongly](https://gnu.org/s/autoconf/manual/html_node/Shell-Substitutions.html)) interpreted as `${10}`, so some 'reversed' care should also be taken:

@@ -34,8 +34,7 @@ dash -c 'set a b c d e f g h i j; echo $10 ${1}0' # WRONG: j a0
### Related resources:

* [BashFaq: How can I access positional parameters after $9?](https://mywiki.wooledge.org/BashFAQ/025)
* [StackOverflow: How to handle more than 10 parameters in shell
](https://stackoverflow.com/questions/4912733/how-to-handle-more-than-10-parameters-in-shell)
* [StackOverflow: How to handle more than 10 parameters in shell](https://stackoverflow.com/q/4912733)
* [Autoconf Manual: Shell Substitutions](https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/html_node/Shell-Substitutions.html) - documents some non-POSIX older shells too

[Source](https://github.com/koalaman/shellcheck/wiki/SC1037)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Shells are space sensitive. Use '< <(cmd)', not '<<(cmd)'.
## Shells are space sensitive. Use `< <(cmd)`, not `<<(cmd)`.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -5,9 +5,9 @@
```sh
for f in *.png
do
cat << EOF
cat << HTML
<img src="$f" /><br/>
EOF
HTML
done > index.html
```
@@ -16,11 +16,12 @@ done > index.html
```sh
for f in *.png
do
cat << EOF
cat << HTML
<img src="$f" /><br/>
EOF
HTML
done > index.html
```

### Rationale:

The here document delimiter will not be recognized if it is indented.
@@ -35,5 +36,6 @@ Removing the indentation is preferred, since the script won't suddenly break if
### Exceptions:

If the line was supposed to be a literal part of the here document, consider choosing a less ambiguous token.

[Source](https://github.com/koalaman/shellcheck/wiki/SC1039)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## When using <<-, you can only indent with tabs.
## When using `<<-`, you can only indent with tabs.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Found 'eof' further down, but not on a separate line.
## Found `eof` further down, but not on a separate line.

Close matches include '-eof' (!= 'eof').

@@ -25,7 +25,7 @@ There is a line containing the terminator you've chosen, but it's not by itself

In the example code, the script uses `<<-eof`, which is the operator `<<-` followed by `eof`. The script therefore looks for `eof` and skips right past the intended terminator because it starts with a dash.

You will get some companion SC1042 errors mentioning lines that contain the string as a substring, though they all point to the start of the here document and not the relevant line:
You will get some companion [[SC1042]] errors mentioning lines that contain the string as a substring, though they all point to the start of the here document and not the relevant line:

```
In foo line 4:
@@ -44,6 +44,7 @@ Try to change the line ending into LF.
None.

---
Note that SC1041 and SC1042 swapped numbers after v0.4.6 to improve the display order. This rare instance of number reuse was justified by them always occuring together on the same line.
Note that SC1041 and [[SC1042]] swapped numbers after v0.4.6 to improve the display order. This rare instance of number reuse was justified by them always occurring together on the same line.

[Source](https://github.com/koalaman/shellcheck/wiki/SC1041)

24 changes: 24 additions & 0 deletions docs/description/SC1042.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## Close matches include `-eof` (!= `eof`).

### Problematic code:

```bash
#!/bin/bash
cat <<-eof
Hello World
-eof
```
### Correct code:
```bash
#!/bin/bash
cat <<- eof
Hello World
eof
```

## Rationale:
See companion error [[SC1041]]. This error occurs at the same time it.
[Source](https://github.com/koalaman/shellcheck/wiki/SC1042)

30 changes: 30 additions & 0 deletions docs/description/SC1043.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## Found EOF further down, but with wrong casing.

### Problematic code:

```sh
cat << EOF
Hello World
Eof
```
### Correct code:
```sh
cat << EOF
Hello World
EOF
```
### Rationale:

ShellCheck found a here document (`<<`) where the end token is missing. However, the end token appears with different case further down. If this was meant to be the end of the here document, make sure the case matches.

### Exceptions:

None. This error is only emitted when the here document is incomplete.

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1043)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Couldn't find end token `EOF' in the here document.
## Couldn't find end token `EOF` in the here document.

### Problematic code:

@@ -20,8 +20,10 @@ The `<<` here document (aka heredoc) was not properly terminated. The terminatin

Note that you can not put here documents in one liners. For such use cases, use a `<<<` here string:

cat << EOF hello world EOF # Wrong: data and terminator can not be on the same line
cat <<< "hello world" # Correct
```sh
cat << EOF hello world EOF # Wrong: data and terminator can not be on the same line
cat <<< "hello world" # Correct
```
### Exceptions:
@@ -30,5 +32,6 @@ None
### Related resources:
* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1044)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# It's not 'foo &; bar', just 'foo & bar'.
# It's not `foo &; bar`, just `foo & bar`.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Couldn't find 'fi' for this 'if'.
## Couldn't find `fi` for this `if`.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## "Expected 'fi' matching previously mentioned 'if'.
## Expected `fi` matching previously mentioned `if`.

See companion warning [[SC1046]].
[Source](https://github.com/koalaman/shellcheck/wiki/SC1047)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Can't have empty then clauses (use 'true' as a no-op).
## Can't have empty then clauses (use `true` as a no-op).

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Did you forget the 'then' for this 'if'?
## Did you forget the `then` for this `if`?

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Expected 'then'.
## Expected `then`.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Semicolons directly after 'then' are not allowed. Just remove it.
## Semicolons directly after `then` are not allowed. Just remove it.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Semicolons directly after 'then' are not allowed. Just remove it.
## Semicolons directly after `then` are not allowed. Just remove it.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Semicolons directly after 'else' are not allowed. Just remove it.
## Semicolons directly after `else` are not allowed. Just remove it.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## You need a space after the '{'.
## You need a space after the `{`.

### Problematic code:

33 changes: 33 additions & 0 deletions docs/description/SC1055.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
## You need at least one command here. Use `true;` as a no-op.

### Problematic code:

```sh
submitbug() {
# TODO: Implement me
}
```

### Correct code:

```sh
submitbug() {
# TODO: Implement me
true
}
```
### Rationale:

ShellCheck found an empty code block. This could be an empty function as shown, a loop with an empty body, or similar.

Sh/bash does not allow empty code blocks. Insert at least one command. If you don't want the block to do anything, `true` (aka `:`) is a good no-op.

### Exceptions:

None

### Related resources:
* [StackOverflow: Why cannot I define an empty function in shell?](https://stackoverflow.com/questions/39307615/why-cannot-i-define-an-empty-function-in-shell)

[Source](https://github.com/koalaman/shellcheck/wiki/SC1055)

22 changes: 22 additions & 0 deletions docs/description/SC1056.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## Expected a `}`. If you have one, try a `;` or `\n` in front of it.

### Problematic code:

```sh
#!/bin/bash
bar() { echo "hello world" }
```
### Correct code:
```sh
#!/bin/bash
bar() { echo "hello world";}
```
### Rationale:
`}` is only recognized as the end of a command group when it's a separate token.
If it's not a separate token, like in the problematic example, it will be considered a literal character, as if writing `echo "foo}"` with quotes, and therefore usually cause a syntax error.
[Source](https://github.com/koalaman/shellcheck/wiki/SC1056)
31 changes: 31 additions & 0 deletions docs/description/SC1057.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
## Did you forget the `do` for this loop?

### Problematic code:

```sh
while read -r line
echo $line
done
```

### Correct code:

```sh
while read -r line
do
echo $line
done
```
### Rationale:

ShellCheck found a loop that appears to be missing its `do` statement. Make sure the loop syntax is correct.

### Exceptions:

None.

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1057)

File renamed without changes.
36 changes: 36 additions & 0 deletions docs/description/SC1059.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## Semicolon is not allowed directly after `do`. You can just delete it.

### Problematic code:

```sh
while true; do; true; done

while true;
do;
true;
done;
```

### Correct code:

```sh
while true; do true; done

while true;
do
true;
done;
```
### Rationale:

Semicolon `;` is not allowed directly after a `do` keyword. Follow it directly with either a command or a linefeed as shown in the example.

### Exceptions:

None.

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1059)

31 changes: 31 additions & 0 deletions docs/description/SC1060.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
## Can't have empty do clauses (use `true` as a no-op)

### Problematic code:

```sh
for i in 1 2 3; do
done
```

### Correct code:

```sh
for i in 1 2 3; do
true
done
```

### Rationale:

An empty `do ... done` block is not valid.
Use `true` or `:` if you need no command at all.

### Exceptions:

None.

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1060)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Couldn't find 'done' for this 'do'.
## Couldn't find `done` for this `do`.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Expected 'done' matching previously mentioned 'do'.
## Expected `done` matching previously mentioned `do`.

See companion warning [[SC1061]]
[Source](https://github.com/koalaman/shellcheck/wiki/SC1062)
44 changes: 44 additions & 0 deletions docs/description/SC1063.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
## You need a line feed or semicolon before the `do`.

### Problematic code:

```sh
for file in * do
echo "$file"
done
```

### Correct code:

```sh
for file in *; do
echo "$file"
done

# or

for file in *
do
echo "$file"
done
```
### Rationale:

ShellCheck found a `do` on the same line as a loop, but `do` only starts a loop block at the start of a line/statement. Make the `do` the start of a new line/statement by inserting a linefeed or semicolon in front of it.

### Exceptions:

If you wanted to treat `do` as a literal string, you can quote it to make this clear to ShellCheck and humans:

```
for f in "for" "do" "done"
do
echo "Shell keywords include: $f"
done
```

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1063)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Expected a { to open the function definition.
## Expected a `{` to open the function definition.

### Problematic code:

@@ -32,10 +32,13 @@ If you are trying to do something else, look up the syntax for what you are tryi

POSIX allows the body of a function to be any compound command, e.g. `foo() for i; do :; done`. Since this usage is rare, ShellCheck intentionally requires the body to be `{ ..; }` (or `( ..; )`):

foo() {
for i; do :; done
}
```sh
foo() {
for i; do :; done
}
```

This additional structure requirement helps improve error messages and suggestions by not parsing down a path that less advanced users wouldn't expect.

[Source](https://github.com/koalaman/shellcheck/wiki/SC1064)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Trying to declare parameters? Don't. Use () and refer to params as $1, $2..
## Trying to declare parameters? Don't. Use `()` and refer to params as `$1`, `$2`, ..

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Don't use $ on the left side of assignments.
## Don't use `$` on the left side of assignments.

### Problematic code:

@@ -20,13 +20,22 @@ declare "$name=hello world"
echo "$foo"
```

Or if you actually wanted to compare the value, use a test expression:

```sh
if [ "$greeting" = "hello world" ]
then
echo "Programmer, I presume?"
fi
```

### Rationale:

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

### Exceptions

None
None.

[Source](https://github.com/koalaman/shellcheck/wiki/SC1066)

File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## You need a space before the [.
## You need a space before the `[`.

### Problematic code:

12 changes: 12 additions & 0 deletions docs/description/SC1070.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Parsing stopped here. Mismatched keywords or invalid parentheses?

### Rationale

ShellCheck found a syntax error at the indicated location. Barring a bug in ShellCheck itself, your shell will also crash with a syntax error at the same location, so you cannot ignore this check.

### Exceptions

None.

[Source](https://github.com/koalaman/shellcheck/wiki/SC1070)

File renamed without changes.
File renamed without changes.
File renamed without changes.
32 changes: 32 additions & 0 deletions docs/description/SC1074.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## Did you forget the `;;` after the previous case item?

### Problematic code:

```bash
while getoptions f option
do
case "${options}"
in
f) FTR="${ARG}"
\?) exit
esac
done
```

### Correct code:

```bash
while getoptions f option
do
case "${options}"
in
f) FTR="${ARG}"
\?) exit;;
esac
done
```

### Rationale:
Syntax `case` needs `;;` after the previous case item. If not, syntax error will cause.
[Source](https://github.com/koalaman/shellcheck/wiki/SC1074)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Use 'elif' instead of 'else if'.
## Use `elif` instead of `else if`.

### Problematic code:

28 changes: 28 additions & 0 deletions docs/description/SC1076.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## Trying to do math? Use e.g. `[ $((i/2+7)) -ge 18 ]`.

### Problematic code:

```sh
[ i / 2 + 7 -ge 18 ]
```

### Correct code:

```sh
[ $((i / 2 + 7)) -ge 18 ]
```
### Rationale:

ShellCheck found a loose `+*/%` in a test statement. This usually happens when trying to do arithmetic in a condition, but without using the arithmetic expansion construct `$((expression))`.

In C, `if (a+b == c)` is perfectly fine, but in sh this must be written to first expand the arithmetic operation like `if [ $((a+b)) = c ]`.

### Exceptions:

None.

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1076)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# For command expansion, the tick should slant left (` vs ´).
# For command expansion, the tick should slant left (`` ` `` vs `´`).


### Problematic code:
File renamed without changes.
File renamed without changes.
28 changes: 28 additions & 0 deletions docs/description/SC1080.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## You need `\` before line feeds to break lines in `[ ]`.

### Problematic code:

```sh
[ "$filename" =
"$otherfile" ]
```

### Correct code:

```sh
[ "$filename" = \
"$otherfile" ]
```
### Rationale:

Bash/ksh `[[ ]]]` can include line breaks anywhere, but `[ ]` requires that you escape them. If you are writing a multi-line `[ .. ]` statement, make sure to include these escapes. If the `[ ]` is supposed to be on a single line, make sure the `]` is there.

### Exceptions:

None

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1080)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Scripts are case sensitive. Use 'if', not 'If'.
## Scripts are case-sensitive. Use `if`, not `If`.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## This file has a UTF-8 BOM. Remove it with: LC_CTYPE=C sed '1s/^...//' < yourscript .
## This file has a UTF-8 BOM. Remove it with: `LC_CTYPE=C sed '1s/^...//' < yourscript`.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## This `{`/`}` is literal. Check expression (missing `;/\n?`) or quote it.
## This `{`/`}` is literal. Check if `;` is missing or quote the expression.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Use #!, not !#, for the shebang.
## Use `#!`, not `!#`, for the shebang.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Don't use $ on the iterator name in for loops.
## Don't use `$` on the iterator name in for loops.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## "Use braces when expanding arrays, e.g. ${array[idx]} (or ${var}[.. to quiet)."
## Use braces when expanding arrays, e.g. `${array[idx]}` (or `${var}[..` to quiet).

### Problematic code:

Original file line number Diff line number Diff line change
@@ -2,16 +2,19 @@

### Problematic code:


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

or


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


### Correct code:

```sh
File renamed without changes.
28 changes: 28 additions & 0 deletions docs/description/SC1090.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## Can't follow non-constant source. Use a directive to specify location.

### Problematic code:

```sh
. "${util_path}"
```

### Correct code:

```sh
# shellcheck source=src/util.sh
. "${util_path}"
```

### Rationale:

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

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

ShellCheck v0.7.2+ will strip a single expansion followed by a slash, e.g. `${var}/util.sh` or `$(dirname "${BASH_SOURCE[0]}")/util.sh`, and treat them as `./util.sh`. This allowing the use of `source-path` directives or `-P` flags to specify the a location.

### Exceptions:

If you don't care that ShellCheck is unable to account for the file, specify `# shellcheck source=/dev/null`.
[Source](https://github.com/koalaman/shellcheck/wiki/SC1090)

Original file line number Diff line number Diff line change
@@ -20,20 +20,26 @@ source somefile
In case you do not have access to the file:

```sh
# shellcheck disable=SC1091
# shellcheck source=/dev/null
source somefile
```

### Rationale:

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

This could be because you did not include it on the command line, did not use `shellcheck -x` to allow following other files, don't have permissions or a variety of other problems.
This could be because:
- you did not include it on the command line,
- did not use `shellcheck -x` (or specified `external-sources=true` in the [[.shellcheckrc|Directive#external-sources]]) to allow following other files
- don't have permissions, or
- a variety of other problems.

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

### Exceptions:

ShellCheck is unable to follow dynamic paths, such as `source "$somedir/file"`. For these cases, see [[SC1090: Can't follow non-constant source. Use a directive to specify location|SC1090]] instead. You may be seeing SC1091 because ShellCheck tried to be helpful and strip a leading dynamic path element as described on that page.

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

[Source](https://github.com/koalaman/shellcheck/wiki/SC1091)
23 changes: 23 additions & 0 deletions docs/description/SC1092.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## Stopping at 100 `source` frames :O

### Problematic code:

An initial file sourcing a second file, which in turn sources a third file, which in turn sources a fourth file, ...., which in turn sources a 100th file.

### Correct code:

Anything but that.

### Rationale:

ShellCheck found a chain of 100+ files sourcing each other. It assumed there must be some internal bug, so it stopped.

### Exceptions:

If this is intentional, you can cosmetically [[ignore]] this message.

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1092)

File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Unexpected ==. For assignment, use =. For comparison, use [/[[.
## Unexpected `==`. For assignment, use `=`. For comparison, use `[`/`[[`.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Quote/escape special characters when using eval, e.g. eval "a=(b)".
## Quote/escape special characters when using `eval`, e.g. `eval "a=(b)"`.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## You need a space before the #.
## You need a space before the `#`.

### Problematic code:

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Delete trailing spaces after \ to break line (or use quotes for literal space).
## Delete trailing spaces after `\` to break line (or use quotes for literal space).

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Shells disambiguate $(( differently or not at all. If the first $( should start command substitution, add a space after it.
## Shells disambiguate `$((` differently or not at all. For `$(command substitution)`, add space after `$(` . For `$((arithmetics))`, fix parsing errors.

### Problematic code:

@@ -26,5 +26,6 @@ Ash, dash and Bash 1 parses it as `$(( (` and subsequently fail to find the matc
**Alternatively**, you may indeed have correctly spaced your parentheses, but ShellCheck failed to parse `$((` as an arithmetic expression while accidentally succeeding in parsing it as `$(` + `(`.

In these cases, double check the syntax to ensure ShellCheck can parse the `$((`, or ignore this error and hope that it won't affect analysis too severely.

[Source](https://github.com/koalaman/shellcheck/wiki/SC1102)

42 changes: 42 additions & 0 deletions docs/description/SC1103.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
## This shell type is unknown. Use e.g. `sh` or `bash`.

### Problematic code:

```sh
# shellcheck shell=zsh
export PAGER=less
```

### Correct code:

Any supported shell on the shebang or the `-s` option

```sh
# shellcheck shell=sh
export PAGER=less
```

### Rationale:

Shellcheck only supports a specific range of shell dialects, there are many more applications providing shell like experiences and some of them look and feel like POSIX shell or bash but does not support the same commands.

One notable unsupported shell type is zsh, see issue [#809](https://github.com/koalaman/shellcheck/issues/809) about supporting zsh - some efforts have been done in the past.

### Exceptions:

The supported shell types are listed in the help context, at the moment these are

* sh
* bash
* dash
* ksh

### Related resources:

- Similar rules
- [[SC1008]] - unrecognized shebang
- [[SC1071]] - unsupported shebang
- [[Documentation for shell directive|Directive#shell]]

[Source](https://github.com/koalaman/shellcheck/wiki/SC1103)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Use #!, not just !, for the shebang.
## Use `#!`, not just `!`, for the shebang.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Shells disambiguate (( differently or not at all. If the first ( should start a subshell, add a space after it.
## Shells disambiguate `((` differently or not at all. If the first `(` should start a subshell, add a space after it.

See [[SC1102]], the similar warning for ambiguous `$((`.
[Source](https://github.com/koalaman/shellcheck/wiki/SC1105)
37 changes: 37 additions & 0 deletions docs/description/SC1106.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## In arithmetic contexts, use `<` instead of `-lt`

Similarly, `>` instead of `-gt`, `<=` instead of `-le`, `>=` instead of `-ge`, `==` instead of `-eq`, `!=` instead of `-ne`.

### Problematic code:

```sh
if (( 2 -lt 3 ))
then
echo "True"
fi
```

### Correct code:

```sh
if (( 2 < 3 ))
then
echo "True"
fi
```

### Rationale:

The comparators `-lt`, `-ge`, `-eq` and friends are flags for the `test` command aka `[`. You are instead using it in an arithmetic context, such as `(( .. ))` or `$(( .. ))`, where you should be using `<`, `>=`, `==` etc instead.

In arithmetic contexts, `-lt` is simply interpreted as "subtract the value of `$lt`", which is clearly not the intention.

### Exceptions:

If you do want to subtract `$lt` you can add a space to make this clear to ShellCheck: `echo $((3 - lt))`

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1106)

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## You need a space before and after the = .
## You need a space before and after the `=` .

### Problematic code:

File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -26,6 +26,12 @@ If you want to use literal slanted double quotes for typographic reasons, you ca
printf 'Warning: “wakeonlan” is not installed.\n'
```

Alternatively, use single slanted Unicode quotes like so:

```sh
printf "Warning: ‘wakeonlan’ is not installed.\n"
```

You can also just [[ignore]] this warning.
[Source](https://github.com/koalaman/shellcheck/wiki/SC1111)

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Use #!, not just #, for the shebang.
## Use `#!`, not just `#`, for the shebang.

### Problematic code:

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Remove spaces between # and ! in the shebang.
## Remove spaces between `#` and `!` in the shebang.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Missing $ on a $((..)) expression? (or use ( ( for arrays).
## Missing `$` on a `$((..))` expression? (or use `( (` for arrays).

### Problematic code:

File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Add a linefeed between end token and terminating ')'.
## Add a linefeed between end token and terminating `)`.

### Problematic code:

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Add ;/& terminators (and other syntax) on the line with the <<, not here.
## Add `;`/`&` terminators (and other syntax) on the line with the `<<`, not here.

### Problematic code:

File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## ShellCheck directives are only valid in front of complete commands like 'case' statements, not individual case branches.
## ShellCheck directives are only valid in front of complete commands like `case` statements, not individual case branches.

### Problematic code:

22 changes: 22 additions & 0 deletions docs/description/SC1125.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## Invalid `key=value` pair in directive

### Problematic code:

```sh
# shellcheck disable=SC2153 (variable not a misspelling)
```

### Correct code:

```sh
# shellcheck disable=SC2153 # variable not a misspelling
```

### Rationale:

A comment at the end of a directive must be preceded by a `#`
to avoid it being interpreted as an instruction.
The [directive page](Directive#documenting-directive-use)
contains more guidance about commenting style.
[Source](https://github.com/koalaman/shellcheck/wiki/SC1125)

File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## You need a space before the !.
## You need a space before the `!`.

### Problematic code:

File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Unexpected start of line. If breaking lines, |/||/&& should be at the end of the previous one.
## Unexpected start of line. If breaking lines, `|`/`||`/`&&` should be at the end of the previous one.

### Problematic code:

@@ -25,7 +25,7 @@ When breaking around a `|`, `||` or `&&`, there are two options:

### Exceptions:

None. This is a syntax error.
In v0.7.2 and below, this warning triggered incorrectly when starting a line with `&>`. In these versions, you can either [[ignore]] the warning, or move the redirection after the command name.

### Related resources:

9 changes: 9 additions & 0 deletions docs/description/SC1134.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Error parsing `shellcheckrc`:

```
SC1134 (error): Failed to process foo, line bar: Fix any mentioned problems and try again.
```

Need more information.
[Source](https://github.com/koalaman/shellcheck/wiki/SC1134)

File renamed without changes.
34 changes: 34 additions & 0 deletions docs/description/SC1136.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
## Unexpected characters after terminating `]`. Missing semicolon/linefeed?

### Problematic code:

```sh
if [ -e "foo.txt" ]: then
echo "Exists"
fi
```

### Correct code:

```sh
if [ -e "foo.txt" ]; then
echo "Exists"
fi
```
### Rationale:

ShellCheck found unexpected characters after the `]` or `]]` in a `test` expression. In the example, a colon was accidentally used instead of a semicolon.

Similarly, a missing space before a comment (`[ -e foo ]#comment`), an additional square bracket (`[[ -e foo ]]]`), or a missing semicolon before a `then` on the same line (`if [ foo ]then`) can cause this warning.

Make sure the `]` or `]]` is not immediately followed by another shell word character.

### Exceptions:

None

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1136)

32 changes: 32 additions & 0 deletions docs/description/SC1137.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## Missing second `(` to start arithmetic for ((;;)) loop

### Problematic code:

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

### Correct code:

```sh
for ((i=0; i<10; i++))
do
echo $i
done
```
### Rationale:

ShellCheck found an arithmetic `for ((;;))` expression where either the `((` or the `))` did not come as a pair. Make sure to use `(( ))` and not `( )`.

### Exceptions:

None.

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1137)

37 changes: 37 additions & 0 deletions docs/description/SC1138.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## Shells are space sensitive. Use `< <(cmd)`, not `<< (cmd)`.

### Problematic code:

```sh
while read -r line
do
echo "You said: $line"
done <<(cmd)
```

### Correct code:

```sh
while read -r line
do
echo "You said: $line"
done < <(cmd)
```
### Rationale:

When redirecting `<` from a process substitution `<(cmd)`, make sure there is a space between the two `<` characters as shown in the example.

With a space `cmd1 < <(cmd2)`, is correctly interpreted as "run cmd1, reading stdin from cmd2, without forking for a pipeline".

Without a space, `<<` is incorrectly considered a here document, and `(cmd2)` is an invalid delimiter token.


### Exceptions:

None

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1138)

38 changes: 38 additions & 0 deletions docs/description/SC1139.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
## Use `||` instead of `-o` between test commands.

And variations, like "Use `&&` instead of `and`".

### Problematic code:

```sh
if [ "$1" = "-v" ] -o [ -n "$VERBOSE" ]
then
echo "Verbose log"
fi
```

### Correct code:

```sh
if [ "$1" = "-v" ] || [ -n "$VERBOSE" ]
then
echo "Verbose log"
fi
```
### Rationale:

You have a `[ .. ]` or `[[ .. ]]` test expression followed by `-o`/`-a` (or by Python-style `or`/`and`).

`-o` and `-a` work *inside* `[ .. ]`, but they do not work *between* them. The Python operators `or` and `and` are never recognized in Bash.

To join two separate test expressions, instead use `||` for "logical OR", or `&&` for "logical AND".

### Exceptions:

None

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1139)

28 changes: 28 additions & 0 deletions docs/description/SC1140.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## Unexpected parameters after condition. Missing `&&`/`||`, or bad expression?

### Problematic code:

```sh
[ "$1" ] input="$1"
```

### Correct code:

```sh
[ "$1" ] && input="$1"
```
### Rationale:

ShellCheck found characters (other than redirections) after the `]` or `]]` in a test expression. This is not valid.

This sometimes happens when there was an additional expression or command, but joining `||` or `&&` is missing. Alternatively, it could happen due to typos (like `[[ $1 ]]]` with an extra `]`), or generally from malformed test expressions.

### Exceptions:

None

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1140)

38 changes: 38 additions & 0 deletions docs/description/SC1141.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
## Unexpected tokens after compound command. Bad redirection or missing `;`/`&&`/`||`/`|`?

### Problematic code:

```sh
while echo "$2"; do true; done \
head -n "$1"

while sleep 1; do date; done > my file
```

### Correct code:

```sh
while echo "$2"; do true; done \
| head -n "$1"

while sleep 1; do date; done > "my file"
```
### Rationale:

ShellCheck found unexpected trailing characters after a compound command.

The only things allowed after compound commands are redirections, shell keywords, and the various command separators (`;`, `&`, `|`, `&&`, `||`).

In the first example, a `|` was missing, causing `head` to appear as an unexpected trailing word, instead of being piped to. In the second example, a lack of quoting caused `file` to appear as an unexpected trailing word, instead of being part of the redirection.

Examine your statement and correct the problem.

### Exceptions:

None

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1141)

38 changes: 38 additions & 0 deletions docs/description/SC1142.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
## Use `done < <(cmd)` to redirect from process substitution (currently missing one `<`).

### Problematic code:

```sh
sum=0
while IFS="" read -r n
do
(( sum += n ))
done <(file)
```

### Correct code:

```sh
sum=0
while IFS="" read -r n
do
(( sum += n ))
done < <(file)
```
### Rationale:

ShellCheck found a `done` keyword followed by a process substitution, e.g. `done <(cmd)`.

The intention was most likely to redirect from this process substitution, in which case you will need one extra `<`: `done < <(cmd)`.

This is because `<(cmd)` expands to a filename (e.g. `/dev/fd/63`), and you need a `<` to redirect from filenames.

### Exceptions:

None

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1142)

54 changes: 54 additions & 0 deletions docs/description/SC1143.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
## This backslash is part of a comment and does not continue the line.

### Problematic code:

```sh
sed \
-e "s/HOST/$HOSTNAME/g" \
# -e "s/USER/$USER/g" \
-e "s/ARCH/$(uname -m)/g" \
"$buildfile"
```

### Correct code:


```sh
sed \
-e "s/HOST/$HOSTNAME/g" \
-e "s/ARCH/$(uname -m)/g" \
"$buildfile"

# This comment is moved out:
# -e "s/USER/$USER/g" \
```

or using backticked, inlined comments:

```sh
sed \
-e "s/HOST/$HOSTNAME/g" \
`# -e "s/USER/$USER/g"` \
-e "s/ARCH/$(uname -m)/g" \
"$buildfile"
```

(ShellCheck recognizes this idiom and does not suggest quotes or `$()`, neither of which would have worked)

### Rationale:

ShellCheck found a line continuation followed by a commented line that appears to try to do the same.

Backslash line continuations are not respected in comments, and the line instead simply terminates. This is a problem when commenting out one line in a multi-line command like the example.

Instead, either move the line away from its statement, or use an `` `# inline comment` `` in an unquoted backtick command substitution.

### Exceptions:

None.

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1143)

28 changes: 28 additions & 0 deletions docs/description/SC1144.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## `external-sources` can only be enabled in .shellcheckrc, not in individual files.

### Problematic code:

```sh
# shellcheck external-sources=true
source /dev/zero
```

### Correct code:

Add `external-sources=true` to `.shellcheckrc`

### Rationale:

Due to its origins as an online tool, ShellCheck will by default run in a sandbox where it only reads the files explicitly named on the command line.

The `external-sources` [[directive]] allows disabling this, but must be specified in `.shellcheckrc`. This is because the sandbox would be useless if the sandboxed script can disable it for itself.

### Exceptions:

None.

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1144)

29 changes: 29 additions & 0 deletions docs/description/SC1145.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## Unknown `external-sources` value. Expected `true`/`false`.

### Problematic code:

`.shellcheckrc`:

```sh
external-sources=maybe
```

### Correct code:

```sh
external-sources=true
```

### Rationale:

The `external-sources` [[directive]] expects a value of `true` or `false`.

### Exceptions:

None.

### Related resources:

* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!
[Source](https://github.com/koalaman/shellcheck/wiki/SC1145)

26 changes: 26 additions & 0 deletions docs/description/SC2000.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# See if you can use `${#variable}` instead

`${#variable}` will be equal to the number of characters in `"${variable}"`

This is the same result as `"$( echo "$variable" | wc -m )"`
When "$variable" only contains single-byte characters, it's also the same as `"$( echo "$variable" | wc -c )"`

## example code

``` 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
```
[Source](https://github.com/koalaman/shellcheck/wiki/SC2000)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## SC2001: See if you can use ${variable//search/replace} instead.
## See if you can use `${variable//search/replace}` instead.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead.
# Useless cat. Consider `cmd < file | ..` or `cmd file | ..` instead.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# expr is antiquated. Consider rewriting this using $((..)), ${} or \[\[ \]\].
# expr is antiquated. Consider rewriting this using `$((..))`, `${}` or `[[ ]]`.

### Problematic code:

@@ -14,9 +14,21 @@ i=$((1+2))
l=${#var}
```

**WARNING:** constants with a leading 0 are interpreted as octal numbers by bash, but not by expr. Then you should specify the base when a leading zero may occur:
```sh
$ x=08
$ echo $(expr 1 + $x)
9
$ echo $((1 + $x))
-bash: 1 + 08: value too great for base (error token is "08")
$ echo $((1 + 10#$x))
9
```
See [issue #1910](https://github.com/koalaman/shellcheck/issues/1910#issuecomment-610439789)

### Rationale:

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

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

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# $/${} is unnecessary on arithmetic variables.
# `$`/`${}` is unnecessary on arithmetic variables.

### Problematic code:

51 changes: 51 additions & 0 deletions docs/description/SC2005.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
Useless `echo`? Instead of `echo $(cmd)`, just use `cmd`
--------------------------------------------------------

### Problematic code:

```sh
echo "$(whoami)"
```

### Correct code:

```sh
whoami
```

### Rationale

ShellCheck found the unnecessary construct `echo "$(somecommand here)"`.

This is generally due to a misunderstanding about what `echo` does. It has no role in "showing on screen" or similar, but simply writes a string to standard output. This is also how all other programs output data.

`echo "$(somecommand)"` will capture the output `somecommand` writes to standard output and write it to standard output, where it was already going. At best this is a no-op, but it may have several other negative effects:

* It disables parallel processing in pipelines, such as `echo "$(find . -name '*.iso')" | xargs sha1sum` which does not allow iterating files and checksumming at the same time. Similarly, users don't see incremental updates as programs run.
* It introduces shell and echo related pitfalls like being unable to output the string `-n`, stripping NUL bytes and trailing linefeeds, and expanding escape sequences in some shells but not others.
* It suppresses the exit code of the command, so that `echo "$(grep '^user:' /etc/passwd)"` no longer returns with failure when the user is not found.
* It does not allow programs to tailor their output for terminals, such as `ls` vs `echo "$(ls)"` where the former outputs columns and colors according to user preferences, while the latter doesn't.
* It uses unnecessary memory to buffer up the data before writing it where it was already going.

To avoid all this, simply replace `echo "$(somecommand)"` with `somecommand` as in the example. It's shorter, faster, and more correct.

### Exceptions

If you are relying on one of the otherwise detrimental effects for correctness, you can consider one of:

```
# Suppress exit code without the other negative effects
cmd || true

# Disable tty specific output without the other negative effects
cmd | cat

# Buffer up potentially large output without using more memory or modifying the content in any way
cmd > file.tmp
cat file.tmp

# Exactly like `echo "$(cmd)"`, but allows output like `-n` and works the same across shells
printf '%s\n' "$(cmd)"
```
[Source](https://github.com/koalaman/shellcheck/wiki/SC2005)

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Use $((..)) instead of deprecated $[..]
## Use `$((..))` instead of deprecated `$[..]`.

### Problematic code

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## SC2009 Consider using pgrep instead of grepping ps output.
## Consider using `pgrep` instead of grepping `ps` output.

### Problematic Code:

@@ -14,7 +14,7 @@ pgrep -f "$service" > /dev/null

### Rationale:

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

If you want a field that's not the pid, consider doing this through `ps` + `pgrep` instead of `ps` + `grep`:

@@ -30,6 +30,8 @@ This is more robust than `ps .. | grep python | cut ..` because it does not try

### Exceptions

`pgrep` is not POSIX. Please [[ignore]] this warning if you are targeting POSIX userlands.

You can [[ignore]] this error if you are trying to match against something that `pgrep` doesn't support:

```
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Don't use ls | grep. Use a glob or a for loop with a condition to allow non-alphanumeric filenames.
## Don't use `ls | grep`. Use a glob or a for loop with a condition to allow non-alphanumeric filenames.

### Problematic code:

@@ -15,7 +15,7 @@ rm $(ls | grep -v '\.c$')
### Correct code:

```sh
echo /directory/*mystring*
ls /directory/*mystring*
```

or
@@ -42,6 +42,7 @@ done
### Exceptions:

- `ls` has sorting options that are tricky to get right with other commands. If a specific order of files is needed, ls _\<sort options\>_ | grep might be the best alternative.
- network shares like AFS behave much faster using ls

### Related resources:

25 changes: 25 additions & 0 deletions docs/description/SC2011.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## Use `find -print0` or `find -exec` to better handle non-alphanumeric filenames.

### Problematic code:

```sh
ls | xargs -n1 wc -w
```

### Correct code:

```sh
find . -maxdepth 1 -print0 | xargs -0 -n1 wc -w
```

```sh
find . -maxdepth 1 -exec wc -w {} \;
```

### Rationale:

Using `-print0` separates each output with a NUL character, rather than a newline, which is safer to pipe into `xargs`. Alternatively using `-exec` avoids the problem of piping and parsing filenames in the first place.

See [[SC2012]] for more details on this issue.
[Source](https://github.com/koalaman/shellcheck/wiki/SC2011)

Original file line number Diff line number Diff line change
@@ -5,13 +5,19 @@
```sh
ls -l | grep " $USER " | grep '\.txt$'
```
```sh
NUMGZ="$(ls -l *.gz | wc -l)"
```

### Correct code:

```sh
find . -maxdepth 1 -name '*.txt' -user "$USER"
find ./*.txt -user "$USER" # Using the names of the files
```

```sh
gz_files=(*.gz)
numgz=${#gz_files[@]} # Sometimes, you just need a count
````
### Rationale:

`ls` is only intended for human consumption: it has a loose, non-standard format and may "clean up" filenames to make output easier to read.
@@ -32,7 +38,9 @@ It shows three seemingly identical filenames, and did you spot the time format c

#### Just the filenames, ma'am

`ls` can usually be replaced by `find` if it's just the filenames you're after. Note that if you are using `ls` to get at the contents of a directory, a straight substitution of `find` may not yield the same results as `ls`. Here is an example:
(Note that `-maxdepth` is not POSIX, but can be simulated by having the expression call `-prune` on all directories it finds, e.g. `find ./* -prune -print`)

`ls` can usually be replaced by `find` if it's just the filenames, or a count of them, that you're after. Note that if you are using `ls` to get at the contents of a directory, a straight substitution of `find` may not yield the same results as `ls`. Here is an example:

```
$ ls -c1 .snapshot
@@ -56,9 +64,9 @@ $ find .snapshot -maxdepth 1
.snapshot/rnapdev1-svm_4_05am_6every4hours.2019-04-02_1205
.snapshot/snapmirror.1501b4aa-3f82-11e8-9c31-00a098cef13d_2147868328.2019-04-01_190000
```
You can see two differences here. The first is that the `find` output has the full paths to the found files, relative to the current working directory from which `find` was run whereas `ls` only has the filenames. You may have to adjust your code to not add the directory to the filenames as you process them when moving from `ls` to `find`.
You can see two differences here. The first is that the `find` output has the full paths to the found files, relative to the current working directory from which `find` was run whereas `ls` only has the filenames. You may have to adjust your code to not add the directory to the filenames as you process them when moving from `ls` to `find`, or (with GNU find) use `-printf '%P\n'` to print just the filename.

The second difference in the two outputs is that the `find` command includes the searched directory as an entry. This can be eliminated by always using a negative name option for the searched directory:
The second difference in the two outputs is that the `find` command includes the searched directory as an entry. This can be eliminated by also using `-mindepth 1` to skip printing the root path, or using a negative name option for the searched directory:
```
$ find .snapshot -maxdepth 1 ! -name .snapshot
.snapshot/rnapdev1-svm_4_05am_6every4hours.2019-04-02_0005
@@ -86,7 +94,7 @@ $ find "$theDir" -maxdepth 1 ! -name "$(basename $theDir)"

#### All the other info

If trying to parse out any other fields, first see whether `stat` (GNU, OS X, FreeBSD) or `find -printf` (GNU) can give you the data you want directly.
If trying to parse out any other fields, first see whether `stat` (GNU, OS X, FreeBSD) or `find -printf` (GNU) can give you the data you want directly. When trying to determine file size, try: `wc -c`. This is more portable as `wc` is a mandatory unix command, unlike `stat` and `find -printf`. It may be slower as unoptimized `wc -c` may read the entire file rather than just checking its properties. On some systems, `wc -c` adds whitespace to the file size which can be trimmed by double expansion: `$(( $(wc -c < "filename") )) `

### Exceptions:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# To read lines rather than words, pipe/redirect to a 'while read' loop.
## To read lines rather than words, pipe/redirect to a `while read` loop.

### Problematic code:

@@ -39,6 +39,15 @@ done < mypipe
rm mypipe
```

NOTE: `grep -v '^ *#'` is a placeholder example and not needed. To just loop through a file:
```sh
while IFS= read -r line
do
echo "Line: $line"
done < file
# or: done <<< "$variable"
```

### Rationale:

For loops by default (subject to `$IFS`) read word by word. Additionally, glob expansion will occur.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Note that A && B || C is not if-then-else. C may run when A is true.
# Note that `A && B || C` is not if-then-else. C may run when A is true.

### Problematic code:

@@ -31,14 +31,13 @@ If an `if` clause is used instead, this problem is avoided.

### Boring detail:


We can think of the example above as
```sh
((([[ $dryrun ]]) && echo "Would delete file") || rm file)
```
expressing the left-associativity of the `&&` `||` operators.

Whenever a command (strictly, a pipeline) succeeds or fails, the execution proceeds following the next `&&` (for success) or `||` (for failure).
Whenever a command (strictly, a pipeline) succeeds or fails, the execution proceeds following the next `&&` (for success) or `||` (for failure). (More strictly, the parentheses should be replaced with `{ command; }` to avoid making a subshell, but that's ugly and boring.)

### Exceptions
Ignore this warning when you actually do intend to run C when either A or B fails.
53 changes: 53 additions & 0 deletions docs/description/SC2016.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Expressions don't expand in single quotes, use double quotes for that.

### Problematic code:

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

### Correct code:

```sh
name=World
echo "Hello $name" # Outputs Hello World
```

### Rationale:

ShellCheck found an expansion like `$var`, `$(cmd)`, or `` `cmd` `` in single quotes.

Single quotes express all such expansions. If you want the expression to expand, use double quotes instead.

If switching to double quotes would require excessive escaping of other metacharacters, note that you can mix and match quotes in the same shell word:

```sh
dialog --msgbox "Filename $file may not contain any of: "'`&;"\#%$' 10 70
```

### Exceptions

If you know that you want the expression literally without expansion, you can [[ignore]] this message:

```
# We want this to output $PATH without expansion
# shellcheck disable=SC2016
echo 'PATH=$PATH:/usr/local/bin' >> ~/.bashrc
```

ShellCheck also does not warn about escaped expansions in double quotes:

```
echo "PATH=\$PATH:/usr/local/bin" >> ~/.bashrc
```

This suggestion is primarily meant to help newbies who assume single and double quotes are basically the same, like in Python and JavaScript. It's not at all meant to discourage experienced users from using single quotes in general. If you are well aware of the difference, please do not hesitate to permanently disable this suggestion with `disable=SC2016` in your `.shellcheckrc`.

ShellCheck tries to increase the signal-to-noise ratio of this warning by ignoring certain well known commands that frequently expect literal dollar signs, such as `sh` and `perl`. However, there's a long tail of less common commands and flags that also frequently expect `$`s, and it's not in ShellCheck's scope to try to keep track of them all. When you come across such a command, please [[ignore]] the suggestion, either permanently or for that one instance.

### Related resources:

* StackOverflow: [How do I use variables in single quoted strings?](https://stackoverflow.com/questions/21192420/how-do-i-use-variables-in-single-quoted-strings)
[Source](https://github.com/koalaman/shellcheck/wiki/SC2016)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Increase precision by replacing a/b\*c with a\*c/b.
## Increase precision by replacing `a/b*c` with `a*c/b`.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Use '[:lower:]' to support accents and foreign alphabets.
## Use `[:lower:]` to support accents and foreign alphabets.

### Problematic code:

@@ -28,6 +28,8 @@ Instead, you can use `[:lower:]` and `[:upper:]` to explicitly specify case:

If you don't want `a-z` to match `é` or `A-Z` to match `Ñ`, you can ignore this message.

As of 2019-09-08, BusyBox `tr` does not support character classes, so you would have to ignore this message.

Note that the examples used here are multibyte characters in UTF-8. Many implementations (including GNU) fails to deal with them.
[Source](https://github.com/koalaman/shellcheck/wiki/SC2018)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Use '[:upper:]' to support accents and foreign alphabets.
## Use `[:upper:]` to support accents and foreign alphabets.

See the equivalent warning for lowercase matching: [[SC2018]]
[Source](https://github.com/koalaman/shellcheck/wiki/SC2019)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# tr replaces sets of chars, not words (mentioned due to duplicates).
## `tr` replaces sets of chars, not words (mentioned due to duplicates).

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Don't use [] around ranges in tr, it replaces literal square brackets.
## Don't use `[]` around ranges in `tr`, it replaces literal square brackets.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Note that unlike globs, o* here matches 'ooo' but not 'oscar'
## Note that unlike globs, `o*` here matches `ooo` but not `oscar`.

### Problematic code:

```sh
24 changes: 24 additions & 0 deletions docs/description/SC2023.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## The shell may override `time` as seen in man time(1). Use `command time ..` for that one.

### Problematic code:

```sh
time -some some
```

### Correct code:

```sh
command time -some some
```

### Rationale:

`time` is a built-in command.
If you would like to use `time` from `$PATH`, you need to use `command` to execute it as a regular command.

### Exceptions:

None
[Source](https://github.com/koalaman/shellcheck/wiki/SC2023)

65 changes: 65 additions & 0 deletions docs/description/SC2024.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
## `sudo` doesn't affect redirects. Use `..| sudo tee file`

or "Use `..| sudo tee -a file`" instead of `>>` to append.

or "Use `sudo cat file | ..`" instead of `<` to read.

### Problematic code:

```
# 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
```

### Correct code:

```
# 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

# Read from a file
sudo cat /etc/shadow | wc -l
```

### Rationale:

Redirections are performed by the current shell before `sudo` is started. This means that it will use the current shell's user and permissions to open and read from or write to the file.

* To *read* from a file that requires additional privileges, you can replace `sudo command < file` with `sudo cat file | command`.
* To *write* to a file that requires additional privileges, you can replace `sudo command > file` with `command | sudo tee file > /dev/null`
* To *append* to a file, use the above with `tee -a`.
* If the file does *not* require special privileges but the command *does*, then you are already doing the right thing: please [[ignore]] the message.

The substitutions work by having a command open the file for reading or writing, instead of relying on the current shell. Since the command is run with elevated privileges, it will have access to files that the current user does not.

Note: there is nothing special about `tee`. It's just the simplest command that can both truncate and append to files without help from the shell. Here are equivalent alternatives:

Truncating:

```
echo 'data' | sudo dd of=file
echo 'data' | sudo sed 'w file'
```

Appending:

```
echo 'data' | sudo awk '{ print $0 >> "file" }'
echo 'data' | sudo sh -c 'cat >> file'
```

### Exceptions

If you want to run a command as root but redirect as the normal user, you can [[ignore]] this message.

[Source](https://github.com/koalaman/shellcheck/wiki/SC2024)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Make sure all escape sequences are enclosed in `\[..\]` to prevent line wrapping issues
## Make sure all escape sequences are enclosed in `\[..\]` to prevent line wrapping issues.

### Problematic code:

File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# echo won't expand escape sequences. Consider printf.
## `echo` won't expand escape sequences. Consider `printf`.

### Problematic code:

File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -18,8 +18,26 @@ n=0
while read i; do (( n+=i )); done < <(printf "%s\n" {1..10})
echo $n
```
In `sh`, temporary files, FIFOs or file descriptors can be used instead. When the output of the command can be stored to a variable before entering the loop, here documents are a preferable alternative:
```sh
n=0
SUMMANDS="$(printf '%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n' 1 2 3 4 5 6 7 8 9 10)"
while read i; do n=$(( n + i )); done <<SUMMANDS_INPUT
$SUMMANDS
SUMMANDS_INPUT
echo $n
```


With Bash 4.2+ you can also use `shopt -s lastpipe` which will change the pipe behaviour to be similar to Ksh and Zsh (see Rationale below) [as long as job control is not active](https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html) (e.g. inside a script):
```bash
#!/usr/bin/env bash
shopt -s lastpipe
n=0
printf "%s\n" {1..10} | while read i; do (( n+=i )); done
echo $n
```

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

### Rationale:

@@ -30,8 +48,8 @@ Here are some constructs that cause subshells (shellcheck may not warn about all
Pipelines:

```sh
subshell1 | subshell2 | subshell3 # Bash, Dash, Ash
subshell1 | subshell2 | regular # Ksh, Zsh
subshell1 | subshell2 | subshell3 # Dash, Ash, Bash (default)
subshell1 | subshell2 | regular # Ksh, Zsh, Bash (with lastpipe=on and no job control)
```

Command substitution:
7 changes: 7 additions & 0 deletions docs/description/SC2032.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This function can't be invoked via su on line 42.
(or from xargs, sudo, chroot, or other commands)

See companion warning [[SC2033]].

[Source](https://github.com/koalaman/shellcheck/wiki/SC2032)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Shell functions can't be passed to external commands.
# Shell functions can't be passed to external commands. Use separate script or sh -c.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,39 +1,41 @@
# foo appears unused. Verify it or export it.

### Problematic code:
## Problematic code:

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

### Correct code:
## Correct code:

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

### Rationale:
## Rationale:

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

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

### Exceptions
## Exceptions

This warning may be falsely emitted when a variable is only referenced indirectly, and for variables that are intentionally unused.

#### Indirection
### Indirection

It's ShellCheck's intended behavior to emit this warning for any variable that is only referenced though indirection:

# foo generates a warning, even though it has five indirect references
foo=42
name=foo
echo "${!name} $((name))"
export "$name"; eval "echo $name"
declare -n name; echo "$name"
```sh
# foo generates a warning, even though it has five indirect references
foo=42
name=foo
echo "${!name} $((name))"
export "$name"; eval "echo $name"
declare -n name; echo "$name"
```

This is an intentional design decision and not a bug. If you have variables that will not have direct references, consider using an associative array in bash, or just [[Ignore]] the warning.

@@ -53,7 +55,14 @@ read _ last _ zip _ _ <<< "$str"
echo "$last, $zip"
```

or if you prefer to keep the names, use a directive to disable the warning:
Or optionally as a prefix for dummy variables (ShellCheck >0.7.2).

```sh ​
read _first last _email zip _lat _lng <<< "$str"
echo "$last, $zip"
```

For versions <= 0.7.2, the message can optionally be [[ignore]]d with a directive:

```sh
# shellcheck disable=SC2034 # Unused variables left for readability
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Use ./\*glob* or -- \*glob* so names with dashes won't become options.
## Use `./*glob*` or `-- *glob*` so names with dashes won't become options.

### Problematic code:
rm *
@@ -23,7 +23,9 @@ Similarly, `--` by convention indicates the end of options, and nothing after it

Note that changing `*` to `./*` in GNU Tar parameters will add `./` prefix to path names in the created archive. This may cause subtle problems (eg. to search for a specific file in archive, the `./` prefix must be specified as well). So using `-- *` is a safer fix for GNU Tar commands.

For more information, see "[Filenames and Pathnames in Shell: How to do it Correctly](http://www.dwheeler.com/essays/filenames-in-shell.html)".
`echo` and `printf` does not have issues unless the glob is the first word in the command. ShellCheck 0.7.2+ does not warn for these commands.

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

[Source](https://github.com/koalaman/shellcheck/wiki/SC2035)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## If you wanted to assign the output of the pipeline, use a=$(b | c) .
## If you wanted to assign the output of the pipeline, use `a=$(b | c)` .

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## To assign the output of a command, use var=$(cmd) .
## To assign the output of a command, use `var=$(cmd)` .

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Use -print0/-0 or find -exec + to allow for non-alphanumeric filenames.
## Use `-print0`/`-0` or `find -exec +` to allow for non-alphanumeric filenames.

### Problematic code:

Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
## In POSIX sh, *something* is undefined.

*Note: This warning has been retired in favor of individual SC3xxx warnings for each individual issue.*

You have declared that your script works with `/bin/sh`, but you are using features that have undefined behavior according to the POSIX specification.

It may currently work for you, but it can or will fail on other OS, the same OS with different configurations, from different contexts (like initramfs/chroot), or in different versions of the same OS, including future updates to your current system.
@@ -94,10 +97,10 @@ POSIX:
The POSIX standard does not allow for exponents. However, you can replicate them completely built-in using a POSIX compatible function. As an example, the `pow` function from [here](http://unix.stackexchange.com/a/7925).

```sh
pow () {
set "$1" "$2" 1
pow() {
set -- "$1" "$2" 1
while [ "$2" -gt 0 ]; do
set "$1" $(($2-1)) $(($1*$3))
set -- "$1" $(($2-1)) $(($1*$3))
done
# %d = signed decimal, %u = unsigned decimal
# Either should overflow to 0
@@ -201,7 +204,7 @@ POSIX:

```sh
echo "$TERM" | sed -e 's/-256.*$//g'
# Special case for this since we are matching the end:
# Special case for this since we are matching the end (the start [#] also works):
echo "${TERM%-256*}"
```

@@ -227,7 +230,6 @@ reuse_quote()(
reuse_quote "$@"
```


### `jobs` flags

The only acceptable flags under POSIX sh for `jobs` are `-l` and `-p` ([see spec](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/jobs.html)). Common flags supported by other shells are `-s` and `-r`, to check for stopped/suspended jobs and running jobs. A portable alternative is using `grep` or `awk`:
@@ -251,23 +253,26 @@ command > file 2>&1 or command 2>&1 | othercommand

No Comments / Exceptions

### Heredoc
### Prefixing signal names with `SIG`

Change:
```
sed 's/some_replacement//g' <<< "${var}"
Instead of e.g.:
```sh
trap my_handler SIGTERM
```

To:
```
printf '%s' "${var}" | sed 's/some_replacement//g'
use:
```sh
trap my_handler TERM
# or (`trap -l` for a list of signal numbers; not every one is portable!)
trap my_handler 15
```

No Comments / Exceptions


## Exception

Depends on what your expected POSIX shell providers would use.

Some features have POSIX proposals:
* `local`: https://www.austingroupbugs.net/bug_view_page.php?bug_id=767
* `$'c-style-escape'`: see above
[Source](https://github.com/koalaman/shellcheck/wiki/SC2039)

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## This is a literal string. To run as a command, use $(..) instead of '..' .
## This is a literal string. To run as a command, use `$(..)` instead of `'..'` .

### Problematic code:

Loading