えんじにあ備忘録

脱よわよわエンジニアを目指すブログ

ファイルをコピーするシェルスクリプトを書きました

本記事はシェルスクリプトの初心者が躓いた箇所をまとめた備忘録です。

動機

AtCoder Problems で Boot camp for Beginners を解くときに、いちいち手動で雛形のファイルをコピー、リネームする手間を省きたかったからです。
また、今まで一からシェルスクリプトを書いたことがなかったので経験を積みたかったのも理由の一つです。

実現したい機能

  • 引数に応じてファイルを保存するディレクトリを変更する
  • リネームするファイル名は 1.cpp、2.cppのように連番にする
  • 引数で渡した数値の範囲でファイルを複数回コピーする
  • 特定のファイル名の場合何もしない

躓きポイント

  • 変数宣言
    except=(1 13 32)のように変数名=値と書きます。
    変数名 = 値とするとそれぞれがコマンドと解釈されエラーになります。

  • 変数の値を参照する

    • 変数の値を他の変数へ設定する var="$var1"
    • 変数と文字列を結合する dir_name="${str}100"
  • forループを使って配列の要素を参照する

for v in "${array[@]}"
do
    echo "$v"
done
  • 一定回数のループ処理を作成する: N 回ループする
for i in `seq 1 N`
dodone
if 条件式1 ; then
  処理1
elif 条件式2 ; then
  処理2
else
  処理3
fi
  • 数値の比較 (num1 と num2 を比較する)

    • -eq :比較する2値が等しければ真となる
    • -nq :比較する2値が等しくなければ真となる
    • -lt :num1 が num2 より小ならば真となる
    • -le :num1 が num2 以下ならば真となる
    • -gt :num1 が num2 より大ならば真となる
    • -ge :num1 が num2 以上ならば真となる
  • 文字列を比較する

    • = :比較する文字列が同一である場合に真となる
    • != :比較する文字列が非同一である場合に真となる
  • 論理積論理和

    • -a :条件式がどちらも真の場合のみ真となる &&でも可能
    • -o :条件式のどちらかが真の場合真となる ||でも可能
    • ! :条件式を反転する
  • booleanを使った条件分岐
    if [ "${boolean}" ]では boolean 値を判定できません。
    if [ 条件式 ];if test 条件式;は同義で、test truetest falseはどちらも true を返します。
    解決策は if "${boolean}";となります。

readonly is_true=true
readonly is_false=false

if "${is_true}"; then
    echo 'is_true'
fi
if "${is_false}"; then
    echo 'is_false'
fi
//出力結果 is_true

完成品

#!/bin/bash
#$./setup100.sh {Medium or Hard} start end

# 作成しないファイル名
except=(1 13 32)

# コマンドライン引数の数をチェック(2以上ならOK)
if [ $# -le 2 ]; then
  echo "Usage: $0 need 2  or more args" 1>&2
  exit 1
fi

# 入力されたコマンドライン引数が期待された値かをチェック
if ! [ "$1" = "Medium" -o "$1" = "Hard" ]; then
  echo "input Medium or Hard" 1>&2
  exit 1
fi
str=$1
dir_name="${str}100"
start=$2
end=$2
if [ $# -eq 3 ]; then
  end=$3
fi

for i in `seq $((start)) $((end))`
do
  file_name=$i
  is_true=true
  for j in "${except[@]}"
  do
    if [ $j = $file_name ]; then
      is_true=false
    fi
  done
  if "${is_true}"; then
      cp -n template_abc.cpp BootCampForBeginners/$dir_name/$file_name.cpp
  fi
done

exit 0

参考

変数を使用する | UNIX & Linux コマンド・シェルスクリプト リファレンス
for 文の使用方法 | UNIX & Linux コマンド・シェルスクリプト リファレンス
シェルスクリプト: コマンドライン引数の数が正しいかチェックする ($#) - まくまく Linux/Shell ノート
Linux シェルスクリプト: コマンドライン引数を取得する ($1, $@, $*) - まくまく Linux/Shell ノート
if 文と test コマンド | UNIX & Linux コマンド・シェルスクリプト リファレンス
bash で boolean を使った if 文 (条件分岐) - Qiita