知ったらもう戻れない!? 便利すぎるZshの世界
- トップページ
- 連載: 初級Linuxerリファレンス
- 知ったらもう戻れない!? 便利すぎるZshの世界
Zshとは
ZshではUnix系OSで利用可能なシェルです。
Bashと同様、プロプライエタリだったksh(Korn Shell)の代替実装として作られたものですが、積極的かつ大幅な強化が行われています。
Zshのドキュメントのイントロダクションには次のように書かれています。
Zsh is a UNIX command interpreter (shell) usable as an interactive login shell and as a shell script command processor. Of the standard shells, zsh most closely resembles ksh but includes many enhancements. It does not provide compatibility with POSIX or other shells in its default operating mode: see the section Compatibility.
(Zshは対話的ログインシェル、あるいはシェルスクリプトプロセッサとして利用できるUNIXコマンドインタプリタ(シェル)です。標準的なシェルの中では、Zshはkshに似ていますが、多くの拡張が含まれています。デフォルトの動作モードではPOSIXや他のシェルとの互換性はありません: 互換性のセクションを参照してください。)
Bashはkshの特性や機能を踏襲していません。Bashの場合、基本的にはPOSIX shellの実装であると言うことができます。そのPOSIX ShellはBourne shellとkshの中間のような存在です。kshが出来た後に制定されましたから、ksh由来の仕様も含まれていますが、kshの機能、例えばksh globなどは含まれていません。
一方、Zshはkshの機能を網羅しつつ、より大幅な強化を行ったシェルです。 対話的機能においては多段階層補完やメニュー補完、インクリメンタル履歴検索など、スクリプト機能では様々なモジュールなど、どちらの面でも非常に強力なシェルとなっています。
通常、Zshは「BashかZshか」のように考えるものではありません。 LinuxにとってはBashは必須のシェルであり、基本部分を担うものです。 一方、Zshはユーザーにとって強力なツールとなるように設計された、追加のソフトウェアです。
ZshのライバルとしてはFishが挙げられることもあります。 Fishと比べ、Zshはその強力さに特化していると言うことができるでしょう。Fishの優れた機能とされるものも、Zshのプラグインとして利用可能であるものもあります。
デフォルトシェル
現在のシステムにおけるデフォルトシェルは次の通りです。
システム | デフォルトシェル |
---|---|
Linux | Bash |
FreeBSD | sh (FreeBSD sh) |
NetBSD | sh (NetBSD sh) |
OpenBSD | ksh (OpenBSD ksh) |
Mac OS X | - |
これはシステムワイドでデフォルトなシェルという意味であり、デフォルトのユーザーシェルという意味ではありません。
ユーザーシェルという点では、Mac OS Xはtcsh, Bash, Zshと変遷しており、FreeBSDはルートのシェルとしてtcshを使います。
Mac OS Xは標準システム上でUnixシェルをインタープリタとして要求するようになっていないため、システムワイドなデフォルトシェルを持たないようです。
現状、システムシェルとしてZshを使うシステムはありません。 Zshは追加のソフトウェアである、と考えて良いでしょう。
Gentoo Linux、及びその派生ディストリビューションはユーザーシェルとしてZshを標準採用する傾向があります。 また、Manjaro Linuxも一時期Zshをユーザーシェルとしていました。
Zshの導入
ZshはLinuxディストリビューションでは一般的にzsh
パッケージによって導入できます。
pacman -S zsh
MSYS2においてもPacmanを使い、Zshを導入することができます。
Mac OS XはCatalinaにおいて、Zshを標準採用しました。 Mac OS XのBashはバージョンが古いままに置かれていることもあり、いくつか問題があります。その点においても、特にMac OS Xでは積極的にZshを使う理由があると言って良いでしょう。
標準でZshを使うようにするには次のようにします。
(/bin/zsh
にあると仮定しています)
chsh /bin/zsh
このまま zsh -l
とすればZshの世界を始めることができますが、ほとんどの場合これでは非常に使いにくいシェルであると感じることでしょう。Zshを使うためには設定が必要です。
少なくとも、compinit
をしなければZshの実力は発揮されません。
grml-zsh-config
The Zsh Manualは非常に長大かつ難解なドキュメントです。 これを読み解くには相当な実力が必要となるでしょう。
しかし、適切な設定を施さねばZshの力は発揮できません。ここで登場するのがgrml-zsh-configです。
GrmlはDebian/GNU LinuxをベースとしたLive-CD Linuxディストリビューションです。 そのGrmlが採用するZshの設定が非常によくできていることから、Zshの設定として人気があります。 そのことも踏まえて、GrmlのZsh設定は単体で公開されています。
Arch Linuxでは grml-zsh-config
パッケージがあり、これを導入することで /etc/zsh/zshrc
として保存されます。
システム全体に対してgrml-zsh-configを設定するには次のようにします。
% sudo wget -O /etc/zsh/zshrc https://git.grml.org/f/grml-etc-core/etc/zsh/zshrc
% wget -O .zshrc https://git.grml.org/f/grml-etc-core/etc/skel/.zshrc
ユーザーローカルに設定したい場合は次のようにします。
% wget -O .zshrc https://git.grml.org/f/grml-etc-core/etc/zsh/zshrc
% wget -O .zshrc.local https://git.grml.org/f/grml-etc-core/etc/skel/.zshrc
これだけでもZshは超強力なシェルに変貌するはずです。
grml-zsh-configは標準でVCSにも対応した優れたプロンプトを持ちます。 しかし、もしもっと違うデザインのプロンプトにしたい場合も話は簡単です。
grml-zsh-configではprompt
という関数が定義されています。
prompt -l
とすることで利用可能なテーマを一覧することができます。そして、例えばprompt adam2
とすればadam2
テーマに切り替わります。
prompt off
とすればこのプロンプト機能が無効になります。
カスタムしたプロンプトを使いたい場合はprompt off
とした後に続けて書いてください。
Zshの機能紹介
メニュー補完
補完時に複数の候補がある状態でTABキーを再度押すと、項目がハイライトされ、カーソルキーによって補完項目を選ぶことができます。
この機能は AUTO_MENU
, MENU_COMPLETE
オプションによって有効になり、デフォルトでAUTO_MENU
が有効です。
なお、デフォルトでは選択肢が4つ以上である場合にメニュー補完となります。 メニュー補完でなくてもタブを連打することで項目を選択することができますが、常にメニュー補完してほしい場合、
zstyle ':completion:*' menu yes select
とすれば選択肢が2つの場合でもメニュー補完となります。
コンテキスト補完
Zshは標準で今のカーソル位置に適切な補完を行うことができます。 次の例ではGitのサブコマンドを補完しています。
これは、Zshの補完機能がプログラマブルだからです。 かなり難しいですが、自分で補完を書くこともできます。
このプログラマブルな補完機能を有効にするには、compinit
関数を呼び出す必要があります。
compinit
関数を有効にするには、autoload -U compinit
とします。
多段階層補完
Zshではディレクトリを再帰的に補完することができます。 次の例では
gen//des
を General/pbsimply-testsite/dest/
に補完しています。
複数候補がある場合、(GLOB_COMPLETE
を有効にすれば)全体をメニュー補完の対象にすることもできますし、曖昧になっている階層から確定することもできます。
この機能はcompinit
によって有効になります。
ZLE
Zshのラインエディタ、ZLEはマルチラインの編集が可能です。
for
などを使ってコマンドが何行にも渡るとき、カーソルで行を移動しながらコマンドを編集することができます。
キーバインドはEmacs, Viの2種類から選ぶことができます。
ZLEを使うにはZLE
オプションを有効にしますが、これはデフォルトでなっています。
履歴検索: コマンド維持
履歴を辿るとき、そのコマンドの履歴だけを辿ることができます。 次の例ではコマンドで履歴を辿るとき、カーソルの位置は終端にしています。
これはZLEのhistory-search-backward
及び
history-search-forward
です。
こうした振る舞いのない、単純な履歴を辿るZLEコマンドとしては、
up-history
と down-history
があります。
履歴剣先: カーソル位置維持
history-beginning-search-backword
及び
history-beginning-search-forward
はカーソル位置を維持しつつ、カーソル位置までが一致する履歴を探索するものです。
例えば.zshrc
において次のようにすることで
bindkey "\e[5~" history-beginning-search-backward
bindkey "\e[6~" history-beginning-search-forward
bindkey -M viins "\e[5~" history-beginning-search-backward
bindkey -M viins "\e[6~" history-beginning-search-forward
bindkey -M vicmd "\e[5~" history-beginning-search-backward
bindkey -M vicmd "\e[6~" history-beginning-search-forward
PageUp/PageDownキーを使ってこの動作ができます。
インライン展開
変数、ヒストリ、グロブなどを入力したあと、TABキーを押すことでその場で展開してしまうことができます。
履歴の使い分け
Zshのfc
コマンドはヒストリ機能に関するコマンドです。
fc -l
でヒストリを一覧することができます。これはhistory
コマンドと同じです。
特に注目すべきは fc -p
及び fc -P
です。
fc -p
はヒストリスタックに新しいヒストリを積みます。このときファイルを指定するとそのファイルをヒストリファイルとして利用します。
これによって作業コンテキストによってヒストリを使い分けることが可能で、Zshの強力なヒストリ検索と合わせて非常に良好な使い勝手が得られます。
fc -p
を引数なしで実行すると匿名のヒストリを積みます。
これは、コマンドを実験したい場合など、ヒストリを汚したくないときに便利です。
fc -P
はヒストリスタックからひとつヒストリを取ります。
次の例ではfc -l
によっていくつものコマンド履歴があり、fc -p
でそのコマンド履歴が新しいものとなり、fc -P
で元に戻っていることが確認できるでしょう。
再帰グロブ
**/
はZshで常に利用できるグロブです。
これは再帰的なディレクトリを意味します。
次の例ではディレクトリレベルによらずLinux
で始まるファイルが補完されていることがわかるでしょう。
拡張グロブ
EXTENDED_GLOB
が有効であれば、さらなる強力なグロブが利用可能になります。これは#
,
~
,
^
の3つの記号がグロブとして有効になることを意味します。
#
はより複雑なグロブのために使いますが、対話的シェルではあまり頻繁に使うものではありません。
^
は否定グロブになります。例えば(^(foo))
とすれば、カレントディレクトリのfoo
以外のファイルに展開されます。(^(foo|bar))
としてfoo
またはbar
ファイル以外とすることもできます。
~
は除外グロブです。例えば **/appl*
で再帰的にappl
で始まるファイルを探しますが、
**/appl*~**/application*~**/orange/*
とすると、その中からapplication
で始まるファイルや、そのファイルが所属するディレクトリがorange
であるファイルは除外します。
(#i)
はグロブをcase-insensitiveにするものです。
数値グロブ
ファイルを数値範囲で指定したい場合は多いものです。
Zshなら<n-m>
というグロブで数値範囲を指定できます。これは、頭に0があってもなくても動作します。
角括弧によるグロブは桁が揃ってないと難しいですが、非常に簡潔に書けます。
NUMERIC_GLOB_SORT
が有効であればファイルは数値順に展開されますが、一般的には有効にしていないでしょう。しかし、glob
qualifierの(n)
と組み合わせることでその場だけ数値順に並べることもできます。
glob qualifier
glob qualifierはグロブによって展開された対象から条件にあるファイルに限定するものです。
glob
qualifierはリンクの数、パーミッション、ファイルサイズ、更新日時、ファイルの属性など非常に幅広い項目から細かく指定できます。特に頻繁に使うのは「通常ファイル」を示す
.
、「ディレクトリ」を示す
/
、「シンボリックリンク」を示す
@
、「空でないディレクトリ」を示す F
です。
glob
qualifierを使うには、BARE_QUAL
オプションを有効にして(.)
のような形で使うか、EXTENDED_GLOB
を有効にして(#q.)
のような形で使います。
修飾子
修飾子はBashでもヒストリには存在する機能ですが、Zshの場合変数展開でも有効です。
これは非常に便利です。修飾子には変換、置き換え、抜粋、パス操作などがあるからです。
特に最後のパスエレメントを返す:t
、最後のパスエレメント以外を返す:h
、拡張子を除外する:r
、拡張子を返す:e
は重宝します。${${i:h}:t}
のようにネストすることができ、これはファイルパスである変数$i
の、最後のディレクトリ(つまり、そのファイルの所属するディレクトリの名前)を返します。
その他のZshの良い点
.*
Bashで .*
を展開すると .
と ..
が含まれてしまうのが悩みどころですが、Zshはこれを含まないのがデフォルトです。
また、そもそも *
がドットファイルを含むかどうかは
GLOB_DOTS
オプションによって制御しますが、 (D)
glob qualifierを使うとこれをコントロールすることができます。
(D)
でGLOB_DOTSが有効になります。明示的に無効にしたい場合は
(^D)
が使えます。
パイプのプロセス
Bashではパイプで実行されるコマンドは全て別のプロセスで実行されます。
これは少し問題があります。それは、パイプ先がwhile
である場合などに、変数の操作やshift
などが別プロセスに閉じ込められてしまい、意図したように動作しないということです。
Bash
4.2以降ではlastpipe
オプションを有効にすることでパイプの最後は同一プロセス内で実行されるようになりました。
Zshはオリジナルのksh同様、パイプの最後のコマンドは同一プロセスで実行されます。
disown
disown
はBashにもある、プロセスをジョブテーブルから削除するコマンドです。
しかし、この使い勝手はZshが勝ります。 まず、ジョブを
&|
をつけてスタートさせると、最初からジョブテーブルに登録せずに開始します。
また、フォアグラウンドで開始してしまったジョブをdisownしたい場合、一回bg
でバックグラウンドジョブにまわしてからdisown
するか、もしくはSIGCONT
を送る必要があります。
しかし、ZshならAUTO_CONTINUE
オプションを有効にすれば、停止中プロセスに対してdisown
すると自動的にSIGCONT
が送られます。
MULTIOS
ZshではMULTIOS
オプションが有効な場合
echo Hello > hell1 > hell2
のように複数のファイルに対してリダイレクトできます。
シェルが提供するパラメータ
Zshは非常に便利な変数がシェルによって提供されます。
一例として、Bashでも$EUID
という変数がシェルによって提供されていますが、これはあくまで読み出し専用です。
しかし、Zshはここに値を書き込むことができ、実際にEUIDが変化します。
PCRE
pcreモジュールを使うとコマンドとして、あるいはconditional expression中で強力な正規表現であるPCREを使うことができます。
なお、conditional
expression中ではEXTENDED_GLOB
相当のグロブを使うことができ、その表現力はPCREには及ばないまでも、正規表現よりもずっと強力です。
強力なモジュール
ZshはC言語で書かれたモジュールを使うことができます。
標準でもPCREのほかにもTCP、UNIXドメインソケット、FTP、FileStat、select(2)などを駆使することができるモジュールが揃っています。
print -l
print
コマンドはecho
よりも素直な解釈をする、使いやすい出力コマンドです。
特に便利なのが-l
オプションで、これは引数を改行区切りで出力します。
複数行に渡る文字列を出力したい場合や、配列/ファイル名生成を明確に分けて表示したい場合に便利です。
read
read
コマンドはシェルスクリプトでは必須のコマンドです。
しかしZshのread
はとびきり強力です。
-t
オプションはタイムアウト秒数を指定することができ、タイムアウトした場合はexit
code 1
で終了します。
-k
オプションは読み込む文字数を指定します。
-q
オプションは1文字だけ読み込み、yesまたはnoを回答させます。
入力がy
またはY
であればexit code
0
で、それ以外の文字であれば1
で、タイムアウトした場合やEOFがきた場合は2
で終了します。
変数名に続けて?
をつけると、後続の文字列がプロンプト文字列として表示されるため、別途print
を使う必要がありません。
エスケープシーケンスつきリテラル
文字列中に改行を入れたい場合、多くのプログラミング言語ではリテラルとして\n
を使うことができますが、シェルではできません。
echo
で改行するのも-e
オプションが必要です。
print
コマンドはこうしたエスケープシーケンスを理解しますが、リテラルとして記述したい場合もあるでしょう。
Zshは$''
というクォートを使うことで、リテラル中でエスケープシーケンスを展開できます。
ヒアストリング
<<
を使ったヒアドキュメントは便利ですが、短いワードを入れたい場合は使いにくく、echo
などをパイプすることが多いでしょう。
Zshでは <<<
というヒアストリングを使って、単一ワードを標準入力から入れることができます。
select
select複合コマンドはselect(2)のZshインターフェイスではなく、選択肢から選ばせるものです。 Zshスクリプトにおいて使います。
例えば次のように書いたとします。
select w in a b c d
do
print $w
done
このスクリプトを実行すると、まず次のように表示されます。
1) a 2) b 3) c 4) d
?#
ここで3を押してエンターを押すと、 $w
の値は
c
になり、select
はプロンプトからループします。
1
から4
以外の値を入力すると $w
の値は空で、select
はプロンプトからループします。
何も入力せずにエンターを押すと、select
は選択肢を表示するところからループします。
EOF(Ctrl+D)を入力すると$w
には何も入らず、select
のループを抜けます。
word … term部分を省略すると、positional
paramater(位置パラメータ、$@
のこと)が使われます。
プログラムでは使いどころがありませんが、関数にすると呼び出しが楽になります。
パラメータ名($w
)も省略すると$REPLY
が使われます。
プロンプト出力
print -P
によって、プロンプトに設定するような%
で始まるエスケープシーケンスを利用可能になります。
特に便利なのが文字小を設定する%F
〜%f
と、背景色を設定する%K
〜%k
です。
これによってechoのような複雑なASCIIシーケンスを使わなくても端末向けのカラー出力が可能です。 例えば
print -P '%F{red}BLUE%f'
とすると赤い文字でBLUEと出力されます。
数値を使うことでカラーコードでの指定も可能です。256色のカラーコードを確認するには
for i in {000..255}; do print -P "$i %K{$i} %k"; done
とすると良いでしょう。
SIGZERR
シェルスクリプトでは「これらの実行がひとつでも失敗したらアウト」というケースは割とあるものです。
このような場合に全て||
をつけるのは見づらいスクリプトになります。
Zshではexit
statusが0
以外の場合、SIGZERR
という仮想のシグナルが発生したように扱うことができます。
これによって、コマンドa
, b
,
c
の3つがひとつでも失敗すれば全体を失敗させたい場合、
(
TRAPZERR() { exit 1 }
a
b
c
) || failed_to_command_function
のように書くことができます。
設定ファイル
zshには5つの設定ファイルがあり、それぞれ/etc/
の下、あるいは$ZDOTDIR
(普通はホームディレクトリ)の下にあるドットファイルとして読まれます。
ファイル名 | ロード条件 |
---|---|
zshenv |
常に |
zprofile |
ログインシェルの場合 |
zshrc |
インタラクティブシェルの場合 |
zlogin |
ログインシェルの場合, zshrcより後 |
zlogout |
ログインシェルをログアウトした場合 |
特に常にロードされるファイルzshenv
を使えるのは、Bashにはない大きな利点です。
また、$ZDOTDIR
によってユーザー設定ファイルの位置をコントロールできるため、設定ファイルそのものを切り替えて使うことも可能です。
Bashのほうが良い点
IPクライアント
Bashでは /dev/tcp/localhost/10000
のようなファイルをリダイレクト先として指定することでIPクライアントとして使うことができますが、Zshではこれができません。
Zshでもzsh/net/tcp
モジュールを使うことでTCP通信はできますが、コマンドラインで使うのにはあまり向いていません。
このモジュールは基本的にはncよりも高度なことをしたい(単にTCPをlistenするだけじゃなく、ちゃんとacceptを取りたいとか)場合に使用するもので、ncよりも簡易なBashが持っているような機能はありません。
なお、この機能はBash固有ではなく、kshに由来します。
関数エクスポート
Bashでは関数をエクスポートすると、関数を環境変数化し、子孫プロセスのBashでその関数を呼び出せるようになっています。
Zshではこのようなことはできません。 特にYadを使う場合などはZshではなくBashを使ったほうが便利なこともあるかもしれません。
しかし、これは必ずしも嘆くようなことではありません。 この機能は潜在的にセキュリティホールとなるからです。
Zshプラグイン
Powerlevel10k
Powerlevel10kはPowerlineとよく似た、Zsh向けのプロンプト拡張です。
驚くべきは、Powerlevel10kそのものがZshで書かれていることです(PowerlineはPythonで書かれています)。
ここまでの動画でもPowerlevel10kのクールなプロンプトを使ってきました。 Powerlevel10kにはVCSに関する機能もあります(Powerlevel10k自体はGitに特化していますが、Powerlevel9kのSubversion及びMercurialの機能を使うこともできます)。
次に示すのはPowerlevel10kのGitプロンプト機能です。 今のディレクトリがGitリポジトリであること、今のブランチがmasterであること、stagedが1、changedが1、untrackedが1であることが示されています。

VCS機能だけに限ればgrml-zsh-configのほうが優れていることには注意が必要です。
Zsh Syntax Highlighting
Fishのように、有効なコマンド、無効なコマンド、存在するファイル、存在しないファイルなどコンテキストごとに色分けしてくれます。
Zsh auto suggestions
Fishのように、入力中の値から履歴、ファイルなどを推測して候補として補完してくれます。
使い勝手への影響が大きく、好みが分かれるでしょう。
Zsh Substring Search
ZLEコマンドとしてhistory-substring-search-up
とhistory-substring-search-down
が追加されます。
これは入力した文字と部分一致するヒストリを辿ります。
検索でも同じことができますが、一致部分がハイライトされるのと、検索コマンドを省略して使えるのがメリットです。
Zshテクニック
ヒストリ検索
Zshのヒストリ検索は強力で便利です。
Viモードでは、ESCでvicmdに入り、/
を押せば検索モードに。
あとは正規表現で探したい文字列を入力して、エンターで検索。n
で遡っていくことができます。
Viモードの検索では正規表現が使えるほうか、「先のほうを探していくと履歴を遡ることになる」のが特徴です。
一方、EmacsモードではCtrl+Rでインクリメンタルサーチができます。
Viモードと違ってインクリメンタルサーチが特徴ですが、後方検索で遡るようになっている点がviとは逆になっています。 さらにCtrl+Rを押すことでその先を探すことができます。
注意点として、現在のヒストリよりも新しいヒストリを検索するキーバインドはデフォルトでCtrl+Sであることです。 Ctrl+Sは大抵の端末において出力停止に割り当てられており、有効ではありません。代えて “Ctrl+X S” が使えますから、覚えておくと良いかもしれません。
forとグロブの使いこなし
forは便利ですが、forのためのリストをコマンドによって生成する必要があるのであれば、それはパイプを使ってwhile read
にしたほうが良いと感じられるでしょう。
Zshはグロブが強力なので、forの活用の余地が増えます。
例えば次の例ではカレントディレクトリを起点に全ての「シンボリックリンクである」.md
ファイルに対して処理を行います。
for i in **/*.md(@)
do
sed -i 's/a Apple/an Apple/g' $i
done
空ディレクトリだけを削除するのも簡単です。for
すら必要ありません。
rmdir **/*(/^F)
バックアップファイルを消すのもfind
は必要ありません。
rm -v **/*"~"(.)
さらに修飾子を使えばリネーマーの実装も簡単です。
次の例では全ての.HTM
, .HTML
,
.htm
,
.htmlx
拡張子を持つファイルの拡張子を.html
に統一します。
for i in **/*.(HTM|HTML|htm|htmlx)
do
mv -v $i ${i:r}.html
done
普通のシェルのラインエディタはシングルラインであり、継続行に入ってからコマンドを編集するのは困難です。このようなfor
コマンドを
for i in **/*.(HTM|HTML|htm|htmlx); do mv -v $i ${i:r}.html;done
のように読みにくい1行に纏めるのは編集の都合もあります。
しかし、Zshはマルチラインのエディタです。セミコロンを使うことなく改行してしまうことで快適にコマンドを入力することができます。
もちろん、Viユーザーであれば、hjkl
による移動だけでなく、行末まで削除(D
)、行結合(J
)、行削除(dd
)といったコマンドが活躍しますし、ループの中身をyyP
として似たコマンドを複製してから一部編集するというのも便利な使い方です。
Zshを設定するには
まずは基本仕様を固めるために、良い設定ファイルを導入するのが良いでしょう。
grml-zsh-configをグローバルな設定ファイルを使うのならば、
sudo wget -O /etc/zsh/zshrc https://git.grml.org/f/grml-etc-core/etc/zsh/zshrc
とします。 個人の設定ファイルとして使うならば
sudo wget -O ~/.zshrc https://git.grml.org/f/grml-etc-core/etc/zsh/zshrc
とします。 どちらの場合も個人の設定ファイルはホームディレクトリ直下の
.zshrc.local
ファイルに書きます(これはgrml-zsh-configの仕様です)。
ディストリビューションによっては標準でホームディレクトリ直下の
.zshrc.d
ディレクトリ以下のファイルを読み込むようになっているかもしれません。
そうなっておらず、そのようにしたい場合、設定ファイルに
for i in ${ZDOTDIR:-$HOME}/.zshrc.d/*(N)
do
source $i
done
のように記述します。
これを実行するには BARE_GLOB_QUAL
オプションが有効である必要があります。 BARE_GLOB_QUAL
が無効で EXTENDED_GLOB
が有効なら (N)
の代わりに (#qN)
と書くことができます。 また、
NULL_GLOB
オプションが有効に場合、 (N)
そのものが必要ありません。
オプションを有効にしたい場合、setopt
を使います。
例えばEXTENDED_GLOB
オプションであれば
setopt EXTENDED_GLOB
とすると有効になります。
逆に無効にするにはunsetopt
を使います。
unsetopt EXTENDED_GLOB
それ以外にもシェルスクリプトとして、コマンドを記述していきます。(例えばzstyle
コマンド)
実行する順序が問題になる場合もありますから、注意してください。
設定の例
私が実際に使用している設定がGitHubで公開されています。 この設定はgrml-zsh-configの利用を前提としていることに注意してください。
解説していきましょう。
まずは ~/.zshrc.local
となるものです。
# -*- mode: zsh; -*-
# vi: set ft=zsh
typeset i
# User's local settings
for i in ${ZDOTDIR:-$HOME}/.zshrc.d/*(.N)
do
source $i
done
# User's site local settings
for i in ${ZDOTDIR:-$HOME}/.zshrc.local.d/*(.N)
do
source $i
done
unset i
~/.zshrc.d/*
にこのリポジトリにある設定ファイルを配置しています。
~/.zshrc.local.d/*
はエイリアスや関数の設定など、マシンごとに固有のものを書きます。
最初に読まれるファイルでは変数をセットします。 この変数は設定ファイルの中で使われます。 どちらもプラグインファイルのパスです。
# -*- mode: zsh; -*-
# vi: set ft=zsh
_ZSH_CONFIG_PLUGINS=(
/usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh)
_ZSH_CONFIG_P10K=/usr/share/zsh-theme-powerlevel10k/powerlevel10k.zsh-theme
#_ZSH_CONFIG_POWERLINE=/usr/share/powerline/bindings/zsh/powerline.zsh
飛んで60ですが、こちらで先程設定した配列変数に指定されたプラグインを呼んでいきます。 私はSyntax Highlightingだけを使っています。
# -*- mode: zsh; -*-
# vi: set ft=zsh
if (( ${#_ZSH_CONFIG_PLUGINS} > 0 ))
then
for i in "${_ZSH_CONFIG_PLUGINS[@]}"
do
source "$i"
done
fi
70はZLEに関する設定です。
設定内容はほとんどがこの記事で紹介したものです。 個人的な好みでViキーバインドにしていることに注意してください。
# -*- mode: zsh; -*-
# vi: set ft=zsh
####### VI mode setting #######
setopt vi
KEYTIMEOUT=1
###############################
# Always use menu.
zstyle ':completion:*' menu yes select
# Menu for full path.
setopt GLOB_COMPLETE
####################################
# inclimental history search #
####################################
autoload -U history-search
bindkey "^P" history-beginning-search-backward
bindkey "^N" history-beginning-search-forward
bindkey "\e[5~" history-beginning-search-backward
bindkey "\e[6~" history-beginning-search-forward
bindkey -M viins "\e[5~" history-beginning-search-backward
bindkey -M viins "\e[6~" history-beginning-search-forward
bindkey -M vicmd "\e[5~" history-beginning-search-backward
bindkey -M vicmd "\e[6~" history-beginning-search-forward
80はヒストリに関する設定です。
ヒストリに関するオプションはgrml-zsh-configで既に設定されているので、変数だけをセットしていきます。 ヒストリファイルの名前を変更し、より多くのヒストリを保存するようにします。
# -*- mode: zsh; -*-
# vi: set ft=zsh
####### History Settings #######
HISTFILE=$HOME/.zhistory
HISTSIZE=10000
SAVEHIST=5000000
################################
90はプロンプトに関する拡張設定です。
環境変数
$_ZSH_PROMPT
が設定されていた場合、~/.zsh.extend.d/$_ZSH_PROMPT
というファイルがあればそのファイルを読み込みます。
そうでない場合は、Powerlevel10kが設定されていて、かつ存在するのであれば、Powerlevel10kを使います。 Powerlevel10kでなく、Powerlineを設定していれば、Powerlineを使います。
Powerlevel10kを使う場合、ZshがMercurialリポジトリ下で起動された場合のみMercurial VCSエンジンを有効にします。 これは、Mercurialエンジンがとても重いことを踏まえて、リポジトリで端末を起動した場合などに限るためです。
# -*- mode: zsh; -*-
# vi: set ft=zsh
if [[ -n $_ZSH_PROMPT && -f ${ZDORDIR:-$HOME}/.zsh.extend.d/$_ZSH_PROMPT ]]
then
source ${ZDORDIR:-$HOME}/.zsh.extend.d/$_ZSH_PROMPT
else
if [[ -n $_ZSH_CONFIG_P10K && -f $_ZSH_CONFIG_P10K ]]
then
prompt off
source $_ZSH_CONFIG_P10K
[[ -f ~/.p10k.zsh ]] && source ~/.p10k.zsh
# If start shell on Mercurial repository, activate Mercurial plugin.
if hg status 2> /dev/null > /dev/null
then
typeset -g POWERLEVEL9K_VCS_BACKENDS=(hg git)
fi
elif [[ -n $_ZSH_CONFIG_POWERLINE && -f $_ZSH_CONFIG_POWERLINE ]]
then
prompt off
source $_ZSH_CONFIG_POWERLINE
fi
fi
最後はオプションです。 これは個別にコメントをつけていきます。
EXTENDED_GLOB
とBARE_GLOB_QUAL
はgrml-zsh-configと重複しますが、重要なのでここで改めて設定しています。
# -*- mode: zsh; -*-
# vi: set ft=zsh
# 拡張グロブを有効にします
setopt EXTENDED_GLOB
# Glob qualifierを有効にします
setopt BARE_GLOB_QUAL
# disownしたときにジョブに自動でSIGCONTを送ります
setopt AUTO_CONTINUE
# バックグラウンドジョブの情報を即時表示します
setopt NOTIFY
# "foo${xx}bar" で $xx が配列のとき、 fooabar foobbar foocbar のように展開します
setopt RC_EXPAND_PARAM
# Ctrl+Dでシェルが閉じないようにします。
setopt IGNORE_EOF
# シェルが閉じたときにバックグラウンドジョブにSIGHUPを送ります。
setopt HUP
# grml-zsh-configはMENU_COMPLETEですが、代わりにAUTO_MENUを使います
setopt AUTO_MENU
# コマンドの代わりにディレクトリを指定するとcdするオプションですが、使いにくいのでオフにします
unsetopt AUTO_CD
# cdがpushd相当になるオプションですが、使い分けたいのでオフにします
unsetopt AUTO_PUSHD
# > で上書きするのを防ぐオプションです。 setopt NO_CLOBBER でも同じです
unsetopt CLOBBER
# 対話的シェルでもコメントを入れられるようにするものです。コピペ時に便利ですが、通常使わないのでオフにします
unsetopt INTERACTIVE_COMMENTS