#author("2018-02-23T14:15:23+09:00","","") #author("2019-04-15T17:49:05+09:00","","") [[bashコーディング規約]] @echo off cd /D %~dp0 SET filename= echo F | xcopy /R %filename% _old\%filename% cd _old rename %filename% %date:/=%_%time::=%_%filename% exit /b #contents * bashコーディング規約 [#f00e2b43] ** 目的(ゴール) [#p8ad2fe0] + Linuxにおける基本的なバッチファイルの作成方法を覚える ** モチベーション [#ta5d5f1a] + 一定の品質を保ちたい + 書くたびに書き方が変わるのは好ましくない * バッチシェルの中身について [#wecbd4d6] ** 宣言 [#k5fc76cf] *** シェバング(shebang) [#g834b4d9] シェバング(shebang)は#!/bin/shではなく#!/bin/bashにする + シバン、シェバンとも言われる + #!/bin/shは実行環境によって様々なシェルにシンボリックリンクになっているので、bashなら#!/bin/bashと明示しよう #!/bin/bash *** インデント [#se2c39c4] インデントは半角スペース2つ + 1行が横に長くなり折り返されないように *** 処理内容および使い方をスクリプト内に記載する(usage()) [#pb7eb098] + 何をしてくれるスクリプトか、どのように使うのかusage()関数を用意しよう ++ ヘッダコメントでもいいけど function usage() { cat <<_EOT_ Usage: $0 [-a] [-b] [-f filename] arg1 ... Description: hogehogehoge Options: -a aaaaaaaaaa -b bbbbbbbbbb -f ffffffffff _EOT_ exit 1 } *** オプション解析を行う(getopts) [#r2e76a0d] #!/bin/bash function usage() { cat <<_EOT_ Usage: $0 [-a] [-b] [-f filename] arg1 ... Description: hogehogehoge Options: -a aaaaaaaaaa -b bbbbbbbbbb -f ffffffffff _EOT_ exit 1 } if [ "$OPTIND" = 1 ]; then while getopts abf:h OPT do case $OPT in a) FLAG_A="on" echo "FLAG_A is $FLAG_A" # for debug ;; b) FLAG_B="on" echo "FLAG_B is $FLAG_B" # for debug ;; f) ARG_F=$OPTARG echo "ARG_F is $ARG_F" # for debug ;; h) echo "h option. display help" # for debug usage ;; \?) echo "Try to enter the h option." 1>&2 ;; esac done else echo "No installed getopts-command." 1>&2 exit 1 fi echo "before shift" # for debug shift $((OPTIND - 1)) echo "display other arguments [$*]" # for debug echo "after shift" # for debug *** 変数の命名規則 [#sa8e2943] *** 定数はreadonly宣言する [#uf66d51d] *** 定数は大文字、定数以外は小文字 [#cc9950c1] readonly CONSTANT_PARAM="hoge" score=100 *** 複数単語の場合は「名詞」と「名詞」を_で結合 [#p2ea5ff1] readonly MAX_NUMBER=100 *** ローカル変数の先頭に_を付ける [#mb78998b] function cal_score_ave() { local _score_sum=0 # ... } *** ファイルおよびディレクトリの命名規則 [#hf9eb60e] + 末尾に/をつけない + readonly宣言して定数にする |対象|命名規則|備考|h |ファイル名(絶対パス)|HOGE_FILE| | |ディレクトリ名(絶対パス)|HOGE_DIR| | |ファイル名(パスなし)|HOGE_FILENAME| | |ディレクトリ名(パスなし)|HOGE_DIRNAME| | |# ファイル名(絶対パス)|readonly HOGE_FILE="/var/tmp/hoge.txt"| | |# ディレクトリ名(絶対パス)|readonly HOGE_DIR="/var/tmp/hoge"| | |# ファイル名(パスなし)|readonly HOGE_FILENAME="hoge.txt"| | |# ディレクトリ名(パスなし)|readonly HOGE_DIRNAME="hoge"| | ** 変数の宣言箇所 [#eed94dcd] ***値を変更する可能性のある場合は冒頭に [#s51e4aa1] +あとで値を変更する場合にわかりやすい 値を変更せず内部的に利用する場合は利用する箇所の直前に +変数と処理の関連性がわかりやすい ** 関数の命名規則 [#udd924fd] *** function宣言する [#f15fa18d] + 小文字で「動詞」と「名詞」を_で結合• usage()は例外 function cal_score_ave() { # ... return 0 } *** 関数は必ずreturnする [#uf3d08eb] function cal_score_ave() { # ... return 0 } *** リターンコード:正常終了は0、異常終了は0以外 [#kbafd80c] *** パイプの前後に半角スペース1つ [#q63ce9df] CMD1 | CMD2 *** リダイレクトの前は半角スペース1つ、後はスペースなし [#ce203a22] CMD1 >hoge.txt CMD1 >>hoge.txt CMD2 <fuga.txt CMD2 <<fuga.txt *** リダイレクトはグルーピングする [#hda06f89] { echo "hoge" echo "fuga" echo "piyo" } >>logfile.log *** 制御構文 [#v81a3663] *** if、thenは同一行に、セミコロンの後ろは半角スペース1つ [#bac811a9] if [ $? -ne 0 ]; then # ... exit 1 fi *** for、whileのdoとdoneを揃える [#r1d1f91a] for _score in ${SCORE_ARRAY[@]} do _score_sum=$((_score_sum + _score)) done while IFS=$`\n` read _line do echo $_line done <hoge.txt *** if文を省略しない [#yd313b43] [ $hoge = $foo ] && echo "true" || echo "false" * 参考情報1.シェルスクリプト Tips [#z41c7516] +2.bash によるオプション解析 + 3.逆引きシェルスクリプト/getoptsを利用して引数を取得する(bashビルドイン) * References [#k5438249] bashコーディング規約参考からリンク2年以上前 - 初心者向けシェルスクリプトの基本コマンドの紹介からリンク約2年前 - bashでshellを作るとき参考になるサイト集からリンク12ヶ月前 - Mac OS Xで時間帯ごとに壁紙を変えたいからリンク2ヶ月前 - Bash で readonly した変数を再度編集可能にするからリンク約1ヶ月前 *追加コメント [#o1d8c80a] Bash, Zsh, Korn shellでしか使えませんが、[よりも[[のほうが一般的な演算子や正規表現が使えるのでオススメです。 http://mywiki.wooledge.org/BashFAQ/031 functionはBash・zshでしか使えないので追記をよろしくお願いします。この書き方で慣れてしまうとShebangが#!/bin/shのスクリプトに手を加えるときに少し面倒なことになります。(その場合はfunction抜きで書きます)