CUBE SUGAR CONTAINER

技術系のこと書きます。

shellcheck でシェルスクリプトのコードの質をチェックする

正しく動作するシェルスクリプトを書くのは難しい。 できれば書きたくないけど、そうもいかない。 そんなとき心の支えになりそうなのが今回紹介する shellcheck というツール。 これはシェルスクリプトにおける Linter (リンター) で、まずい書き方をしているとそれを教えてくれる。

使った環境は次の通り。

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.13.5
BuildVersion:   17F77

下準備

まずは shellcheck をインストールする。 macOS であれば Homebrew でインストールするのが楽ちん。

$ brew install shellcheck

インストールすると shellcheck コマンドが使えるようになる。

$ shellcheck -V
ShellCheck - shell script analysis tool
version: 0.5.0
license: GNU General Public License, version 3
website: https://www.shellcheck.net

使ってみる

試しに、意図的にまずいシェルスクリプトを書いてそれをチェックしてみよう。

例えば、こんなコードを用意してみる。 一見すると、特に問題はなさそうな気もする。

$ cat << 'EOF' > example.sh 
#!/bin/sh

echo Time: `date`
EOF

実行しても、ちゃんと動くし。

$ sh example.sh 
Time: 201878日 日曜日 185226秒 JST

とはいえ、これを shellcheck 先生にかけると、次のようにいくつか指摘を受ける。 例えば SC2046 はクオートが足りないという指摘で、SC2006 はインラインのコマンド実行には `` よりも $() を使うべきという指摘。

$ shellcheck example.sh

In example.sh line 3:
echo Time: `date`
           ^-- SC2046: Quote this to prevent word splitting.
           ^-- SC2006: Use $(..) instead of legacy `..`.

上記の指摘を直してみよう。

$ cat << 'EOF' > example.sh 
#!/bin/sh

echo "Time: $(date)"
EOF

再度実行すると、今度は何も言われない。

$ shellcheck example.sh 

他にも、例えばシングルクオートで囲んでいるので展開されない変数があるパターンとか。

$ cat << 'EOF' > example.sh 
#!/bin/sh

echo 'Can not expand with single quote: $PATH'
EOF

これも、次の通りちゃんと教えてくれる。

$ shellcheck example.sh

In example.sh line 3:
echo 'Can not expand with single quote: $PATH'
     ^-- SC2016: Expressions don't expand in single quotes, use double quotes for that.

あとは、地味にやりがちな lsfor 文に突っ込んじゃうやつとか。 これはファイル名やディレクトリ名にスペースが入っていると動かない。

$ cat << 'EOF' > example.sh 
#!/bin/sh

for f in $(ls); do
  echo "${f}"
done
EOF

これもちゃんと教えてくれる。

$ shellcheck example.sh

In example.sh line 3:
for f in $(ls); do
         ^-- SC2045: Iterating over ls output is fragile. Use globs.

ばっちり。

めでたしめでたし。