bashシェルスクリプト入門3

筆者がよく使うシェルスクリプトをまとめました。

ファイル数を調べる

lsコマンドとwcコマンドを使って、カレントディレクトリの*.png の個数を調べます。wc --lineは行数を表示します。

wcって何?

word countが名前の由来ね。
バイト数、単語数、行数を表示するコマンドよ

$ ls *.png | wc --line
13

$ png_cnt=$(ls *.png | wc --line)
$ echo $png_cnt
13Code language: Bash (bash)

ただし、*.pngが0個の場合、stderrに「ls: '*.png' にアクセスできません: そのようなファイルやディレクトリはありません」と表示されてしまいます。

$ ls *.png | wc --line
ls: '*.png' にアクセスできません: そのようなファイルやディレクトリはありません
0

$ png_cnt=$(ls *.png | wc --line)
ls: '*.png' にアクセスできません: そのようなファイルやディレクトリはありません

$ echo $png_cnt
0Code language: Bash (bash)

エラーみたいで、気になるわ

pngファイルが1個もない。

「*.png」をシェル展開できない。

「*.png」というファイルを探した。

そのようなファイルはない。

さいわい、png_cntには0が設定されて、結果は期待どおりです。

このメッセージが気になる場合は、findコマンドを使います。「-maxdepth 1」を指定すろと、カレントディレクトリだけを探し、サブディレクトリ下を検索しません。

$ find . -name "*.png" -maxdepth 1 | wc --line
13

$ png_cnt=$(find . -name "*.png"  -maxdepth 1 | wc --line)
$ echo $png_cnt
13Code language: Bash (bash)

「-maxdepth 1」を指定しなければ、サブディレクトリを含めて、*.png の個数を調べます。

$ find . -name "*.png" | wc --line
13

$ png_cnt=$(find . -name "*.png"  | wc --line)
$ echo $png_cnt
13Code language: Bash (bash)

ファイルサイズを調べる

ファイルサイズが 0より大きいかを調べるには、ファイルテスト演算子 -s を使います。ファイルが存在しない場合は、ファイルサイズ=0として判断されます。

#!/bin/bash -ue

if [ -s "myfile.txt" ]; then
  echo "filesize > 0"
else
  echo "filesize = 0"
fi
Code language: Bash (bash)

ファイルが存在することを確認したい場合は、ファイルテスト演算子 -f を使います。

#!/bin/bash -ue

if [ -f "myfile.txt" ]; then
  echo "file exists"
else
  echo "file not exists"
fi
Code language: Bash (bash)

ファイルサイズ=0で、ファイルが存在することを確認したい場合は、-f と -s を組み合わせて使います。

#!/bin/bash -ue

file="myfile.txt"

if [ ! -f $file ]; then
  echo "file not exists"
else
  if [ -s "myfile.txt" ]; then
    echo "filesize > 0"
  else
    echo "filesize = 0"
  fi
fi
Code language: Bash (bash)

else if って書けないの?

書いてもいいけど、期待している else if とは違うと思うわ。

ファイルサイズ1000以上かどうかって調べられるのかな?

statコマンドの"-c %s"オプションで、ファイルサイズを調べます。

file statusを表示するので、statコマンドね。

ファイルが存在しないとき、size=""(空白)となり、続く、if文の比較でエラーになってしまいます。そこで、size=${size:-0}で、sizeが空白なら0、とするようにしています。

-ge は、数値比較の >= の意味です。

#!/bin/bash -ue

file="myfile.txt"

size=$(stat -c %s $file)
size=${size:-0}

if [ $size -ge 1000 ]; then
  echo "size >= 1000"
else
  echo "size < 1000"
fi
Code language: Bash (bash)

wc --bytes でもファイルサイズがわかるね

んー、たしかにそうだけど、
statコマンドのほうが速いから、
wc --bytesを使う場面はあまりないわね

npmのpackage.jsonのversionをインクリメントする

Jenkinsでdevelopブランチから引っぱってきて、各種テストに合格したら、versionをインクリメントして、masterブランチにコミットしてpush、という場面です。

ここでは、npmの設定ファイルpackage.jsonのversionの末尾をインクリメントします。次のような場合は、「19」を「20」にします。

{
  "name": "jquery-jpostal-ja",
  "version": "2.13.19",Code language: JSON / JSON with Comments (json)

"2.13"の部分は、手作業で編集してgit commitするんだね。

シェルスクリプトとsedで処理します。

JSONフォーマットだから、nodejsで処理したほうが自然かもね

npm_increment_version.sh

#!/bin/bash -ue

# package.jsonのversion項目、先頭にスペース2個あり
#
#  "version": "2.13.19",
#↓
#  "version": "2.13.20",
#
# cur_ver: 19
# new_ver: 20
# message: 2.13.20

cur_ver=$(cat package.json | grep -e "^  \"version" | sed -r "s/^(  \"version\": \"[0-9]+\.[0-9]+\.)([0-9]+)(\",)/\2/")
echo "cur_ver:" $cur_ver

new_ver=$((cur_ver + 1))
echo "new_ver:" $new_ver

cat  package.json | sed -r "s/^(  \"version\": \"[0-9]+\.[0-9]+\.)([0-9]+)(\",)/\1$new_ver\3/" >tmp.json

cp  tmp.json  package.json
rm tmp.json

message=$(cat  package.json | grep -e "^  \"version" | sed -r "s/^(  \"version\": \")([0-9]+\.[0-9]+\.[0-9]+)(\",)/\2/")
echo "message:" $messageCode language: Bash (bash)
$ ./npm_increment_version.sh
cur_ver: 19
new_ver: 20
message: 2.13.20Code language: Bash (bash)

正規表現って他の人にはわからないよね

書いた本人だって、すぐには思い出せないわよ

タイトルとURLをコピーしました