APIを使った独自シェルをつくろう(祝日付きカレンダーcal3・天気情報wx)

著者画像
Toshihiko Arai

祝日付きカレンダー(内閣府API)

cal コマンドはlinuxやmacOSのターミナルでカレンダーを表示できるシェルです。ターミナルで高速表示できるカレンダーは地味に便利で重宝しています。

項目 コマンド
今月のカレンダーを表示 cal
指定した月のカレンダーを表示 cal 3 2024
年間カレンダーを一覧で表示 cal 2024
先月、当月、翌月のカレンダーを表示 cal -3

とくに先月・当月・翌月を表示する cal -3 が便利なのですが、祝日も表示できないかと調べたところ、以下の方法がありました。

cal -3; curl -s https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv | iconv -f SHIFT-JIS -t UTF-8 | grep -E "`date -v-1m '+%Y/%-m/'`|`date '+%Y/%-m/'`|`date -v+1m '+%Y/%-m/'`"

実行結果:

$ cal3
      8月 2025              9月 2025              10月 2025
日 月 火 水 木 金 土  日 月 火 水 木 金 土  日 月 火 水 木 金 土
                1  2      1  2  3  4  5  6            1  2  3  4
 3  4  5  6  7  8  9   7  8  9 10 11 12 13   5  6  7  8  9 10 11
10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18
17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25
24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31
31
2025/8/11,山の日
2025/9/15,敬老の日
2025/9/23,秋分の日
2025/10/13,スポーツの日

内閣府が発行している祝日のcsvデータをcurlでフェッチし、iconvでshift-jisからutf-8へ文字エンコード処理を行います。そして、csvデータの中から、cal -3のカレンダー表示に合わせて先月、当月、翌月の祝日データをgrepでフィルタリングして表示させてます。

.zshrccal3 などで登録しておくと便利です。

alias cal3="cal -3; curl -s https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv | iconv -f SHIFT-JIS -t UTF-8 | grep -E \"\$(date -v-1m '+%Y/%-m/')|\$(date '+%Y/%-m/')|\$(date -v+1m '+%Y/%-m/')\""

参考: https://iwb.jp/terminal-cal-command-calendar-holiday-list/

天気情報取得(気象庁API)

気象庁のデータAPIが公開されているので cal3 同様にそちらを利用して天気、気温、風速などの情報を表示させます。

curl https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json | jq

参考:

取得した json を整形して出力させる処理を、 wx としてコマンド化し、 .zshrc に登録させました。

alias wx="curl -s 'https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json' \
  | jq -r '
    .[0].timeSeries[0] as \$ts0 |
    .[0].timeSeries[1] as \$ts1 |
    .[0].timeSeries[2] as \$ts2 |
    \"地域: \(\$ts0.areas[0].area.name)\n天気: \(\$ts0.areas[0].weathers[0])\n風: \(\$ts0.areas[0].winds[0])\n波: \(\$ts0.areas[0].waves[0] // \"-\")\n降水確率: \(\$ts1.areas[0].pops[0] // \"-\")/\(\$ts1.areas[0].pops[1] // \"-\")/\(\$ts1.areas[0].pops[2] // \"-\")/\(\$ts1.areas[0].pops[3] // \"-\")\n最高気温: \(\$ts2.areas[0].temps[0] // \"-\")℃\n最低気温: \(\$ts2.areas[0].temps[2] // \"-\")℃\"
  '"

実行結果:

$ wx
域: 東京地方
天気: くもり 時々 雨 所により 夕方 雷を伴い 非常に 激しく 降る
風: 南西の風 後 北東の風 23区西部 では 南西の風 やや強く
波: 1メートル 後 0.5メートル
降水確率: 50/60/60/60
最高気温: 32℃
最低気温: 24℃

https://www.jma.go.jp/bosai/forecast/#area_type=offices&area_code=130000

残念ながらmacOSのターミナルからGP取得する方法が見つからなかったため、位置情報は決め打ちにしました。

地震情報(気象庁API)

地震などの災害時は、サイトアクセス過多で接続できないことがよくありますが、次のようにjsonファイルだけならアクセスできるかもしれませんね。

# 地震情報(直近1週間分)
quake() {
  curl -s "https://www.jma.go.jp/bosai/quake/data/list.json" \
  | jq -r '
    ["日時","震源地","M","最大震度"],
    (
      .[]
      | select((.anm // "") != "")
      | (.at | sub("\\+09:00$"; "") | strptime("%Y-%m-%dT%H:%M:%S")) as $ts
      | select(($ts | mktime) >= (now - 7*24*60*60))
      | [
          ($ts | strftime("%Y-%m-%d %H:%M")),
          .anm,
          (.mag // "-"),
          (.maxi // "-")
        ]
    )
    | @tsv
  ' \
  | column -t -s $'\t'
}

使い方:

$ quake
日時              震源地                M    最大震度
2025-09-13 12:19  秋田県内陸北部        2.6  1
2025-09-13 11:38  カムチャツカ半島付近  7.5
2025-09-13 05:03  伊豆大島近海          2.4  1
2025-09-13 03:09  薩摩半島西方沖        2.1  1
2025-09-13 00:57  北海道東方沖          4.7  2
2025-09-13 00:48  宮城県沖              3.7  1
2025-09-12 19:57  山梨県東部・富士五湖  2.8  1

私のmacOS環境の dotfiles をGitHubで公開してますので何かの参考に

シェルからChatGPTを呼び出す(OpenAI API)

以下の方法はOpenAI APIキーが必要になります。事前にクレジットの購入が必要です。
https://platform.openai.com/

次のように、ターミナルからChatGPTに直接質問するシェルスクリプトを作ってみました。

#!/bin/bash

API_KEY="sk-..."  # OpenAIのAPIキー
ENDPOINT="https://api.openai.com/v1/chat/completions"
MODEL="gpt-4o"

# 入力を標準入力から取得
INPUT=$(cat)

# 入力をJSONエスケープ(1行の安全な文字列に)
ESCAPED_INPUT=$(printf '%s' "$INPUT" | jq -Rs .)

# JSONリクエストボディを組み立て
JSON=$(cat <<EOF
{
  "model": "$MODEL",
  "messages": [
    {
      "role": "system",
      "content": "あなたは日本語で答えるAIアシスタントです。"
    },
    {
      "role": "user",
      "content": $ESCAPED_INPUT
    }
  ],
  "temperature": 0.7
}
EOF
)

# APIリクエスト送信
RESPONSE=$(curl -s "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $API_KEY" \
  -d "$JSON")

# エラーチェック
if echo "$RESPONSE" | jq -e '.error' > /dev/null; then
  echo "エラー: $(echo "$RESPONSE" | jq -r '.error.message')" >&2
  exit 1
fi

# 出力
echo "$RESPONSE" | jq -r '.choices[0].message.content'

使い方は次のとおり:

# 例1
echo "ChatGPTとは何ですか?" | ./chatgpt.sh
# 例2
cat q.txt | ./chatgpt.sh

2025年3月時点の OpenAI API モデル料金

モデル 入力(Prompt) 出力(Response)
gpt-3.5-turbo 0.0005ドル / 1,000トークン 0.0015ドル / 1,000トークン
gpt-4-turbo 0.01ドル / 1,000トークン 0.03ドル / 1,000トークン
gpt-4o(おすすめ) 0.005ドル / 1,000トークン 0.015ドル / 1,000トークン

GhostScript でPDFの圧縮

ここからは API ではありませんが、便利なライブラリのエイリアス化を紹介します。

macOSでPDFをコマンドラインで圧縮する方法で、自炊などで電子書籍化したPDFデータの容量を圧縮したい時におすすめです。

GhostScript というソフトウェアを使ってPDFを圧縮します。macOSの場合は brew を使ってインストールできます。

パッケージ バージョン インストールコマンド
gs 10.01.2 brew install ghostscript

次のように圧縮したいPDF in.pdf を次のコマンドで圧縮して out.pdf として書き出すことができます。

gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile=out.pdf in.pdf

試してみたところ、138MBあったPDFが76MBへ削減できました!およそ50%の圧縮です! PDFSETTINGS オプションを変更することで圧縮率を高める方法もありますが、電子書籍だと文字が読めない状態になってしまいましたのでここでは紹介しません。

ワンライナー化してエイリアスに登録しました。

# PDF圧縮
alias pdfmin='f(){ input="$1"; output="${input%.*}_min.pdf"; gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile="$output" "$input" && echo "$output"; }; f'

モノによっては大して圧縮されなかったり、圧縮自体がエラーになってうまく書き出せなかったりしますのでご注意ください。圧縮エラーになるファイルが結構ありました。

Amazonで探す