言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

  1. トップページ
  2. Bash辞典
  3. bashとzshの違い

bashとzshの違い

macOS Catalina(2019年)以降、デフォルトシェルが『bash』から『zsh』に変更されました。両者の構文はほぼ同じですが、配列のインデックスやグロブの挙動など、知らずにハマるポイントがあります。このページではスクリプトを書くときに注意すべき違いをまとめます。

主な違い一覧

項目bashzsh
配列の開始インデックス0 始まり1 始まり
変数の単語分割$var はスペースで自動分割$var は分割しない(安全)
グロブ(**)shopt -s globstar が必要デフォルトで使える
マッチなしグロブパターン文字列がそのまま残るエラーになる(nomatch)
プロンプト変数\u、\h、\w%n、%m、%~
オプション設定shopt -s オプション名setopt オプション名
設定ファイル~/.bashrc~/.zshrc
補完システムbash-completion(外部)compinit / compsys(組み込み)
右プロンプトなしRPROMPT で設定可能
スペル修正なしsetopt correct で有効

サンプルコード

配列の開始インデックスが異なります。bash は 0 始まり、zsh は 1 始まりです。

bash の場合
fruits=("apple" "banana" "cherry")
echo ${fruits[0]}
apple
echo ${fruits[1]}
banana
zsh の場合
fruits=("apple" "banana" "cherry")
echo ${fruits[1]}
apple
echo ${fruits[2]}
banana

bash ではクォートなしの変数がスペースで自動分割されますが、zsh では分割されません。

bash の場合
msg="hello world"
for word in $msg; do echo "[$word]"; done
[hello]
[world]
zsh の場合
msg="hello world"
for word in $msg; do echo "[$word]"; done
[hello world]

再帰グロブ(**)を使ってサブディレクトリのファイルを検索します。bash では事前に『shopt -s globstar』が必要です。

bash の場合
shopt -s globstar
ls **/*.txt
zsh の場合
ls **/*.txt

グロブがどのファイルにもマッチしない場合の挙動が異なります。bash はパターン文字列をそのまま渡しますが、zsh はエラーを返します。

bash の場合
ls *.xyz
ls: *.xyz: No such file or directory
zsh の場合
ls *.xyz
zsh: no matches found: *.xyz

プロンプトの設定記法が異なります。

bash の場合(~/.bashrc)
PS1='\u@\h:\w\$ '
zsh の場合(~/.zshrc)
PS1='%n@%m:%~%# '
意味bashzsh
ユーザー名\u%n
ホスト名\h%m
カレントディレクトリ\w%~
プロンプト記号(root は #)\$%#

シェルオプションの設定方法が異なります。

bash の場合
shopt -s nocaseglob
shopt -s globstar
shopt -u nocaseglob
zsh の場合
setopt no_case_glob
setopt glob_star_short
unsetopt no_case_glob

概要

シェルスクリプト(『#!/bin/bash』)として書いたファイルは bash の構文で実行されるため、普段 zsh を使っていてもスクリプトの動作には影響しません。違いが問題になるのはターミナルで直接コマンドを打つ場合や、『~/.bashrc』と『~/.zshrc』の設定を書く場合です。

最も注意すべきは配列の開始インデックスの違いです。bash は 0 始まり、zsh は 1 始まりのため、同じスクリプトでも結果が変わります。移植性を重視するなら『#!/bin/bash』を明記して bash で実行してください。

シェバンの使い方は シェバン(shebang)/ chmod +x を、変数の展開については ${パラメータ展開} を、for 文のグロブ活用は for を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。