1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

zsh で echo ===== と書くと「==== not found」で止まる — = で始まる語はコマンドのパスに展開される

1
Last updated at Posted at 2026-11-03

はじめに

📝 この記事は note ・ Zenn にも投稿しています。

2日がかりで、Mac で動かしている自動ジョブの棚卸しをしていた。ログや設定をまとめて読むために、コマンドを ; でつなぎ、ジョブごとに区切りの行を出していた。

echo ===step7; tail -n 20 step7.log; echo ===step9; tail -n 20 step9.log

返ってきたのは1行だけだった。

(eval):1: ==step7 not found

tail の出力も、2つ目の区切りも出ない。終了コードは1。区切りのつもりで書いた echo が、1つ目で全体を止めていた。

同じ形を、この2日間で2回踏んでいる。1回目で気づいたのに、対策を書き残さなかった。その後も、別の作業の最初の調査コマンドで3回目を踏んだ。

= で始まる語は、コマンドのパスになる

zsh には EQUALS というオプションがあり、既定で有効になっている。語の先頭が = だと、その後ろをコマンド名として探し、見つかったパスに置き換える。

zsh 5.9(macOS 標準)で、設定ファイルを読まずに試した。

zsh -f -c 'echo =ls'
# /bin/ls

=ls は /bin/ls になる。which ls を埋め込んだのと同じ働きをする。

= が2つ以上続くと、先頭の1つを外した残りがコマンド名として探される。

zsh -f -c 'echo ==ls'
# zsh:1: =ls not found
zsh -f -c 'echo ===step7'
# zsh:1: ==step7 not found
zsh -f -c 'echo ====='
# zsh:1: ==== not found

===== は ==== というコマンドを探しに行き、そんなコマンドは無いので展開が失敗する。

後ろのコマンドまで止まる

展開の失敗は、そのコマンドだけでは終わらなかった。

書き方 出たもの 終了コード
echo ===step7; echo after ==step7 not found だけ 1
echo ===step7 && echo after 同上 1
echo ===x || true; echo after 同上 1
改行で区切る(echo before / echo ===step7 / echo after) before のあと止まる 1
スクリプトファイルに書く 同上 1
関数の中(f(){ echo ===x; echo in-f; }; f; echo after-f) どれも出ない 1
サブシェル(( echo ===x ); echo after) after が出る 0

; で区切っても、改行で区切っても、そこで止まる。|| true を付けても続かない。展開の失敗は「コマンドが失敗した」ではなく、コマンドを組み立てる前の段で起きているので、|| が効く場所まで届かない。

続いたのは、( ) でサブシェルに閉じ込めたときだけだった。サブシェルの中で止まり、外側は次の行へ進む。

同じ1行を bash 3.2(macOS 標準の /bin/bash)で流すと、そのまま表示される。

bash -c 'echo ===step7; echo after'
# ===step7
# after

bash には = の展開が無い。bash で書いていた区切りを zsh に持ち込むと、ここで止まる。

止まらない書き方

区切りの行は、引用符で囲めば展開されない。

zsh -f -c "echo '====='; echo after"
# =====
# after

= 以外で始めてもいい。echo --- も echo '[step7]' も、そのまま出た。

オプションを切る方法もある。

zsh -f -c 'setopt noequals; echo ===step7; echo after'
# ===step7
# after

ただ、noequals はそのシェルの中だけで効く。毎回のコマンドの頭に足すより、= で始まる語を引用符なしで書かないほうが手間が少なかった。

= が語の途中にある場合は展開されない。echo a=b は a=b と出る。= 1文字だけの echo = も、そのまま = が出た。危ないのは、語の先頭が = で、後ろに何か続く形だけだ。

AI にシェルを打たせるとき

この3回は、どれも Claude Code にコマンドを組ませていたときに出た。Claude Code の Bash ツールは、Mac では利用者のログインシェル(ここでは zsh)で動く。区切りに ===== を使う書き方は bash でも Python の出力でもよく見る形で、手癖として出てきやすい。

1回の呼び出しに調べものを ; で詰めていると、最初の区切りで全部が止まり、返ってくるのは not found の1行になる。何も調べられていないのに、エラーの文面からは区切りの行が原因だと分かりにくい。

いまは作業のメモに「区切りは最初から echo '-----' と引用符つきで書く」と残している。


区切りの線を引いたつもりだった。zsh には、それが ==== という名前のコマンドを探せ、という指示に見えていた。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?