セットアップ - zsh

# はじめに

[**セットアップ シリーズ**](https://qiita.com/yokarikeri/items/a4e41a36c610bb1c798b)、zsh 編。

## 構成

この記事では、以下について説明する。

- コマンドラインシェル: [**zsh**](https://www.zsh.org/)（ズィーシェル）
- zsh 構成フレームワーク: [**Prezto**](https://github.com/sorin-ionescu/prezto)（プレズト）
- zsh テーマ: [**Powerlevel10k**](https://github.com/romkatv/powerlevel10k)
- フィルタリングツール: [**Peco**](https://github.com/peco/peco)

**tmux** は[別記事](https://qiita.com/yokarikeri/items/1c9a228fc9b462c53755)にまとめたので、そちらを参照のこと。

## 環境

今回、検証に使った環境は以下のとおり。

| OS                        | 端末エミューレーター          | zsh                                 |
| ------------------------- | ----------------------------- | ----------------------------------- |
| macOS 10.15 Catalina      | ターミナル.app                | zsh 5.8 (x86_64-apple-darwin19.3.0) |
| Ubuntu 20.04 LTS on WSL 2 | Windows Terminal v1.5.10271.0 | zsh 5.8 (x86_64-ubuntu-linux-gnu)   |

以下、「端末エミューレーター」（ターミナル）を「端末」と呼ぶ。

![構成イメージ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116759/b968c74b-a473-cd23-4d6c-f35d9c756bc3.png)

## zsh について

macOS Catalina 以降（2019 年）で、[macOS のデフォルトシェルが zsh に変更された](https://support.apple.com/en-us/HT208050)のは記憶に新しい。（[経緯](https://kanasys.com/tech/803#index1-0)）

zsh は Bash の拡張版のような立ち位置で、ものすごい数の機能を持つ。
誕生は意外にも古く、Bash の翌年（1990 年）らしい。

## fish について

zsh より現代的と言われる **fish**（2005 年 ～）は、POSIX シェル互換性が低いようなので、ひとまず採用を見送り中。

## ショートカットキーの表記

本記事では、Emacs キーバインド風に、ショートカットを以下のように省略する。

- **`C-`** ... `Ctrl` キー / `control`（`⌃`）キー
- **`S-`** ... `Shift`（`⇧`）キー
- **`A-`** ... `Alt` キー / `option`（`⌥`）キー
- **`D-`** ... `command`（`⌘`）キー
    - macOS のみ。

例えば、`Ctrl + Shift + Alt + a` なら、`C-S-A-a` と表記する。

また、連続して入力する場合は「スペース」を使う。
例えば `Ctrl + X` の直後に `Y` を入力なら、`C-X Y`と表記する。

# 👑 コマンドラインシェル: [zsh](https://www.zsh.org/)（ズィーシェル）

## zsh のインストール

**確認:**

`zsh` が未インストール、または、バージョンが古ければ、最新版の `zsh` をインストールする。

```sh
$ which zsh && zsh --version
```

**macOS でのインストール:**

デフォルトの zsh は古いので、Homebrew で最新版をインストールする。

```sh
$ brew install zsh
```

**Ubuntu でのインストール:**

```sh
$ sudo apt install zsh
```

**適用:**

```sh
# 確認
$ which zsh && zsh --version
/usr/bin/zsh
zsh 5.8 (x86_64-ubuntu-linux-gnu)

# ログインシェルの選択候補に、インストールした zsh が登録済みか確認
$ grep "$(which zsh)" /etc/shells

# 上記の結果 /etc/shells になければ、zsh のパス（which zsh の結果）を追記しておく。
## e.g.
## $ sudo sh -c "echo '$(which zsh)' >> /etc/shells"

# ログインシェルを zsh に変更
$ chsh --shell "$(which zsh)"

# 端末を再起動

# 確認
$ echo $SHELL
/usr/bin/zsh
```

## zsh の設定

最終的な本記事による `~/.zshrc` の内容は以下のとおり。

```sh
# Executes commands at the start of an interactive session.

# ================================
#  Loading file
# ================================

# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
# Executes commands at the start of an interactive session.
# Initialization code that may require console input (password prompts, [y/n]
# confirmations, etc.) must go above this block; everything else may go below.
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
  source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi

# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh

# Source Prezto.
if [[ -s "${ZDOTDIR:-$HOME}/.zprezto/init.zsh" ]]; then
  source "${ZDOTDIR:-$HOME}/.zprezto/init.zsh"
fi


# ================================
#  Loading zsh function
# ================================

# Enable compinit.
autoload -Uz compinit
compinit

# Enable powerlevel10k.
autoload -Uz promptinit
promptinit
prompt powerlevel10k

# Enable cdr.
# cf. http://zsh.sourceforge.net/Doc/Release/User-Contributions.html#index-cdr
autoload -Uz chpwd_recent_dirs cdr add-zsh-hook
add-zsh-hook chpwd chpwd_recent_dirs
zstyle ':completion:*:*:cdr:*:*' menu selection
zstyle ':completion:*' recent-dirs-insert both
zstyle ':chpwd:*' recent-dirs-max 500
zstyle ':chpwd:*' recent-dirs-default true
zstyle ':chpwd:*' recent-dirs-file "${XDG_CACHE_HOME:-$HOME/.cache}/shell/chpwd-recent-dirs"
zstyle ':chpwd:*' recent-dirs-pushd true

# Enable zmv
autoload -Uz zmv


# ================================
#  Other zsh settings
# ================================

# ignore C-D logout
setopt IGNOREEOF

# silent
setopt no_beep

# Set ls colors
if [[ -f ~/.dircolors && $(which dircolors) ]]; then
  eval $(dircolors -b ~/.dircolors)
  zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
fi


# ================================
#  Keybinds
# ================================

# C-U: Same as Bash
## Change before: kill-whole-line
bindkey \^U backward-kill-line

# C-R: peco-history-selection
## Change before: history-incremental-search-backward
function peco-history-selection {
  BUFFER=$(\history -nr 1 | peco)
  CURSOR=${#BUFFER}
}
zle -N peco-history-selection
bindkey \^R peco-history-selection

# C-S: peco-cdr-selection
## Change before: history-incremental-search-forward
function peco-cdr-selection {
  BUFFER="cd $(cdr -l | awk '{ print $2 }' | peco)"
  CURSOR=${#BUFFER}
}
zle -N peco-cdr-selection
bindkey \^S peco-cdr-selection


# ================================
#  Aliases
# ================================

# use alias with sudo
# cf. https://manpages.debian.org/bullseye/manpages-ja/bash.1.ja.html#alias~2
alias sudo='sudo '

# -i ... force pre-execution confirmation
alias cp='cp -i'
alias mv='mv -i'
alias rm='rm -i'

# -l ... long listing
# -a ... list entries starting with .
# -F ... append file type indicators for /
# -h ... print sizes in human readable form
alias ll='ls -laFh'

# -n ... suppress line numbers
# -i ... yyyy-mm-dd format time-stamps
# -D ... print elapsed times
alias history='history -niD'

# -a ...  print all occurrences in path
alias which='which -a'

# noglob ... Do not expand meta characters.
# -W ... Use wildcards without parentheses
alias zmv='noglob zmv -W'

# Show clock
## If you don't want to stop the SSH session.
alias showclock='watch -n 60 date'

# psql tsv output
# SHOULD TEST ME
alias psqltsv='psql -AF $'\''\t'\'''


# ================================
#  Environment variables
# ================================

# Date and time format
## longer: YYYY-MM-DD W hh:mm:ss Z
### export TIME_STYLE='+%F %a %T %Z'
## middle: YYYY-MM-DD hh:mm:ss
export TIME_STYLE='+%F %T'
## shorter: MM-DD hh:mm
### export TIME_STYLE='+%m-%d %H:%M'

# Overwrite .zprofile (Prezto)
export EDITOR='vim'
export VISUAL='vim'

# less
## -i ... ignore case in searches that lack uppercase
## -R ... display control chars; keep track of screen effects
## -W ... highlight first unread line after forward movement
## (-S ... truncate long lines instead of folding)
export LESS='-iRW'
```

### （補足）zsh キーバインドについて

- キーバインドの空きを探す:
    - cf. [zsh のキーバインドで余っているキーを探す - mollifier delta blog](https://mollifier.hatenablog.com/entry/20081213/1229148947)
- `Esc` の代替キーバインド:
    - `C-[`

# 👑 zsh 構成フレームワーク: [Prezto](https://github.com/sorin-ionescu/prezto)（プレズト）

- zsh を適切なデフォルト、エイリアス、関数、補完、プロンプトテーマで強化する。
- [oh-my-zsh](https://github.com/ohmyzsh/ohmyzsh) より高速らしいので採用。
    - cf. [zsh フレームワークの起動速度＆設定の楽さ比較！ - Qiita](https://qiita.com/qwerty/items/92412925ac2cb9eabf4c)

**注意:**

- `~/.zshrc` が存在しないことを確認しておくこと。
    （上書きされるので、必要なら退避すること）

**インストール:**

```sh
# 公式の手順に従って prezto をインストール & 構成ファイルを配置
$ git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"

$ setopt EXTENDED_GLOB
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
  ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
done

# ~/ 配下に .zlogin, .zlogout, .zpreztorc, .zprofile, .zshenv, .zshrc が生成される

# 端末を再度起動
# プロンプトが ❯❯❯ に変更されていることを確認

# デフォルトのエディターが `nano` なので、好みに応じて `vi` や `vim` などに変更
## ここで定義されているので
$ grep nano ~/.zprofile
export EDITOR='nano'
export VISUAL='nano'

## ~/.zshrc の末尾に追記する
$ vi ~/.zshrc
export EDITOR='vi'
export VISUAL='vi'

# 反映
$ . ~/.zshrc

## 確認
$ grep vi ~/.zshrc
export EDITOR='vi'
export VISUAL='vi'
```

**主な設定確認 - 環境変数:**

- history の保存先は `~/.zhistory` になっている。

```sh
echo $HISTFILE
```

**主な設定確認 - zsh オプション:**

> cf. [zsh: 16 Options](http://zsh.sourceforge.net/Doc/Release/Options.html)

- history にタイムスタンプを付与する `EXTENDED_HISTORY` (`extendedhistory`) などが有効になっている。

```sh
$ setopt | grep hist
extendedhistory
histexpiredupsfirst
histfindnodups
histignorealldups
histignoredups
histignorespace
histsavenodups
histverify
sharehistory
```

- `cd` なしで、パスだけ打ち込むとディレクトリーを移動できる。

```sh
$ setopt | grep autocd
autocd
```

**アップデート:**

> cf. <https://github.com/sorin-ionescu/prezto#updating>

```sh
cd $ZPREZTODIR && git pull && git submodule update --init --recursive
```

# 👑 zsh テーマ: [Powerlevel10k](https://github.com/romkatv/powerlevel10k)

zsh の配色（プロンプトテーマ）を構成してくれるツール。

**注意:**

- 事前に [Nerd Fonts](https://github.com/ryanoasis/nerd-fonts)（アイコンのフォント）を含むフォントをインストールし、**端末のフォント**に設定しておくこと。
- 今回は日本語フォントを含む [HackGenNerd Console](https://github.com/yuru7/HackGen/releases) を採用。
    （Regular、Bold、Italic、Bold Italic がすべて利用可能か確認しておくこと）

**インストール:**

```sh
# zsh のテーマ一覧で、powerlevel10k が既に選択可能なことを確認
$ prompt -l | grep powerlevel10k

# zsh のテーマとして powerlevel10k を選択
$ prompt -s powerlevel10k

## 対話式コマンドで、表示が正しいか確認される
## フォントが正しくインストール & 設定されていれば、すべて NO の選択肢になるはず
## その後、引き続き対話式コマンドで、好みのテーマを作成できる
## 対話式コマンドが終了すると、選択内容に応じたテーマに変更される

# 上記コマンド後の表示されるメッセージに従い、.zshrc の末尾に以下を追記
## 追記するまで、選択したテーマは保存されない
$ vi ~/.zshrc
autoload -Uz promptinit
promptinit
prompt powerlevel10k

# 反映
$ . ~/.zshrc
```

# 👑 フィルタリングツール: [Peco](https://github.com/peco/peco)

> cf. [peco を使ったらターミナルの操作が劇的に効率化できた話 - Qiita](https://qiita.com/sukebeeeeei/items/9b815e56a173a281f42f)
> cf. [peco を使って端末操作を爆速にする - Qiita](https://qiita.com/reireias/items/fd96d67ccf1fdffb24ed)
> cf. [Sample Usage · peco/peco Wiki](https://github.com/peco/peco/wiki/Sample-Usage)

コマンドの実行履歴などを、非常に便利に検索できるツール。

今回は、Peco を使うためのラッパー関数には [anyframe](https://github.com/mollifier/anyframe) などは使わず、手直しの簡便さを優先して `.zshrc` に直接記載する。

**macOS:**

```sh
brew install peco
```

**Ubuntu:**

```sh
sudo apt install peco
```

**手順:**

```sh
# 確認
$ peco --version
peco version v0.5.1

# 以下を追記
## C-R でコマンド履歴を呼び出せるように。
## C-S キーで今まで移動したことのあるディレクトリーへ移動できるように。
$ vi ~/.zshrc
```

```sh
# Enable compinit.
autoload -Uz compinit
compinit

# Enable cdr.
# cf. http://zsh.sourceforge.net/Doc/Release/User-Contributions.html#index-cdr
autoload -Uz chpwd_recent_dirs cdr add-zsh-hook
add-zsh-hook chpwd chpwd_recent_dirs
zstyle ':completion:*:*:cdr:*:*' menu selection
zstyle ':completion:*' recent-dirs-insert both
zstyle ':chpwd:*' recent-dirs-max 500
zstyle ':chpwd:*' recent-dirs-default true
zstyle ':chpwd:*' recent-dirs-file "${XDG_CACHE_HOME:-$HOME/.cache}/shell/chpwd-recent-dirs"
zstyle ':chpwd:*' recent-dirs-pushd true

# C-R: peco-history-selection
function peco-history-selection {
  BUFFER=$(\history -nr 1 | peco)
  CURSOR=${#BUFFER}
  zle reset-prompt
}
zle -N peco-history-selection
bindkey \^R peco-history-selection

# C-S: peco-cdr-selection
function peco-cdr-selection {
  BUFFER="cd $(cdr -l | awk '{ print $2 }' | peco)"
  CURSOR=${#BUFFER}
  zle reset-prompt
}
zle -N peco-cdr-selection
bindkey \^S peco-cdr-selection
```

```sh
# 反映
$ . ~/.zshrc
```

**補足:**

- 端末起動時にエラーが出る場合は、`~/.zshrc` の zsh 組み込み関数 `compinit` を見直すべきことが多い。詳細は以下の記事が詳しい。
    - cf. [compinit のセキュリティオプション - ywatase の日記](https://ywatase.hatenablog.com/entry/20071103/p1)
- よくお勧めされる [zsh-completions](https://github.com/zsh-users/zsh-completions) は不要と思われる。
    - 少なくとも導入前後で `~/.zcompdump` の内容は、ほとんど変わらなかった。

## 入力補完の強化

brew 補完
[Homebrew Shell Completion — Homebrew Documentation](https://docs.brew.sh/Shell-Completion#configuring-completions-in-zsh)

heroku 補完
[Heroku CLI 用の zsh 設定は不要だった件 / マスタカの ChangeLog メモ](https://masutaka.net/chalow/2018-10-28-1.html)
`heroku autocomplete --refresh-cache`

docker 補完
[Command-line completion | Docker Documentation](https://docs.docker.com/compose/completion/)

```sh
etc=/Applications/Docker.app/Contents/Resources/etc
ln -s $etc/docker.zsh-completion /usr/local/share/zsh/site-functions/_docker
ln -s $etc/docker-compose.zsh-completion /usr/local/share/zsh/site-functions/_docker-compose

$ https://github.com/docker/docker/blob/master/contrib/completion/zsh/_docker
$ https://github.com/docker/compose/blob/master/contrib/completion/zsh/_docker-compose
$ curl -L https://raw.githubusercontent.com/docker/compose/1.27.4/contrib/completion/zsh/_docker-compose \
  > ~/.zsh/completion/_docker-compose
$ exec $SHELL -l
```

# 🔧 zsh の細かな設定

## ls コマンドの色変更

**GNU 版 ls コマンド**用の色が見づらかったので、修正。
（一部の「背景色」と「文字色」が同系色で見づらい）

**注意:**

この手順は **macOS** のデフォルトである **BSD 版 ls コマンド** 用**ではない**点に注意。

**手順:**

[dircolors コマンド](https://linuxjm.osdn.jp/html/gnumaniak/man1/dircolors.1.html) で、デフォルトのカラー構成情報をコピーして使う。
設定可能な色は [ISO 6429 (ANSI) カラーシーケンス](https://linuxjm.osdn.jp/html/LDP_man-pages/man5/dir_colors.5.html#lbAD) を参照。

```sh
# デフォルトのファイルをコピー
$ dircolors -p > ~/.dircolors

# 以下のように変更（文字色を黒に、黒字に合わない背景色を変更）
$ vi ~/.dircolors
```

```diff
- OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky
+ OTHER_WRITABLE 30;46 # dir that is other-writable (o+w) and not sticky
- STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable
+ STICKY 30;44 # dir with the sticky bit set (+t) and not other-writable
```

```sh
# 以下を追記して、ls コマンドの配色と、zsh のファイル名補完の配色を変更
$ vi ~/.zshrc
eval $(dircolors -b ~/.dircolors)
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}

# 反映
$ . ~/.zshrc
```

ちなみに `eval` を使っているのは、単に `dircolors -b <path>` の出力結果が `LS_COLORS=<色情報>` なので、そのまま式を評価すれば環境変数 `LS_COLORS` に代入できるため。

また `${(s.:.)LS_COLORS}` の変数展開は、zsh の [Parameter Expansion Flags](https://gist.github.com/sho-t/d9cdf8271b3de7c4238739e523490542#triangular_flag_on_post-%E5%A4%89%E6%95%B0%E5%B1%95%E9%96%8B%E3%83%95%E3%83%A9%E3%82%B0parameter-expansion-flags-zzz) の `s` フラグを使った split を使っている。

## zmv コマンドの有効化

> cf. [zmv - zsh: 26 User Contributions](http://zsh.sourceforge.net/Doc/Release/User-Contributions.html#index-zmv)

zsh 組み込みコマンド `zmv` は、ファイル名を**一括リネーム**できる。

**有効化の手順:**

```sh
# 以下を追記
$ vi ~/.zshrc
```

```sh
# Enable zmv
autoload -Uz zmv

# noglob ... Do not expand meta characters.
# -W ... Use wildcards without parentheses
alias zmv='noglob zmv -W'
```

```sh
# 反映
$ . ~/.zshrc
```

**使い方:**

以下のように、一括リーネームできる。

```sh
# 確認用に、任意のファイルを用意する。
$ cd <任意のフォルダー>
$ touch foo.txt bar.txt baz.txt

# リネームを実行せず、結果を事前に確認する
$ zmv -n *.txt *.csv
mv -- bar.txt bar.csv
mv -- baz.txt baz.csv
mv -- foo.txt foo.csv

# リネームを実行
$ zmv *.txt *.csv
```

**主なオプション:**

- `-n`: リネームを実行せず、結果を事前に確認する。
- `-C`: 移動ではなく、コピーする
- `-f`: ファイルが存在しても上書きする

**その他:**

- [変数展開](https://gist.github.com/sho-t/d9cdf8271b3de7c4238739e523490542)や[算術式](https://kanasys.com/tech/803#index4-7)を活用して、ファイル名に連番を付与することもできる。
    - ただし、今回は `.zshrc` の alias で定義している `noglob` によって式の挙動が変わるため、コマンド名に `\` を付けて alias をエスケープ（無視）する必要がある。
    - e.g. `c=1 \zmv -n '(*).txt' '${1}-$((c++)).txt'`

# 付録: zsh に関する細かいこと

## その他の zsh の機能

- GNU Redline キーバインド互換
    - Bash などと同じく、emacs に似たキーバインドで行を操作できる。
        - cf. [Readline Cheat Sheet](https://readline.kablamo.org/emacs.html)
    - ちなみに、zsh のキーバインドは `readline` ではなく、独自の zsh 組み込みコマンド `zle`（[Zsh Line Editor](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html)）を使っている。
        - cf. [18.6.1 Movement - zsh: 18 Zsh Line Editor](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Movement-1)
- buffer stack（コマンドラインスタック）
    - `zle` の機能により、入力中のコマンドをスタックに退避できる。
        使いたい場面に出くわしていないが、一応掲載しておく。
    - cf. [「漢の zsh」で取り上げてほしいネタ案 @ val it: α → α = fun](http://www.jmuk.org/diary/index.php/2007/06/08/0/)

## zsh の設定でよく使うコマンド

細かい調整のために。

- `setopt` コマンド
    - zsh のシェルとしてのオプションを設定する zsh 組み込みコマンド。
        - cf. [setopt - zsh: 17 Shell Builtin Commands](http://zsh.sourceforge.net/Doc/Release/Shell-Builtin-Commands.html#index-setopt)
    - 引数を指定しない場合、オプション一覧を表示する。
        オプション名は、なぜか区切り文字のない小文字のみで、大変読み辛い。
        - cf. [zsh でシェルスクリプトを書くときの留意点 - 拡張 POSIX シェルスクリプト Advent Calendar 2013 - ダメ出し Blog](https://fumiyas.github.io/2013/12/03/zsh-scripting.sh-advent-calendar.html)
- `autoload` コマンド
    - 環境変数 `FPATH` や `fpath` で指定されたファイル内のシェル関数を、その関数の初回実行時に自動的に読み込み、関数を使えるようにするための zsh 組み込みコマンド。
    - cf. [9.1 Autoloading Functions - zsh: 9 Functions](http://zsh.sourceforge.net/Doc/Release/Functions.html#Autoloading-Functions)
- `zstyle` コマンド
    - 補完機能（Completion System）などを操作する zsh 組み込みコマンド。
    - zsh にはスタイルとタグという概念があり、補完機能ならタグは補完対象が何であるかを示し、スタイルはそれをどのように補完するかを示す。
    - cf. [zstyle - 22.37 The zsh/zutil Module - zsh\_ 22 Zsh Modules](http://zsh.sourceforge.net/Doc/Release/Zsh-Modules.html#index-zstyle)
    - cf. [zsh: 20 Completion System](http://zsh.sourceforge.net/Doc/Release/Completion-System.html)

## ログインシェルとインタラクティブシェル

> cf. [2.1: Types of shell: interactive and login shells - A User's Guide to the Z-Shell](http://zsh.sourceforge.net/Guide/zshguide02.html#l7)

zsh 特有の話ではないが、「ログインシェルか？」や「インタラクティブシェルか？」は、気にし出すとややこしい。

例えば、Ubuntu Desktop の「GNOME 端末」など、GUI の端末からシェルを起動する場合は、ログインシェルではない。
ただし、macOS は GUI だが、「ターミナル.app」（デフォルト端末）や、「iTerm2.app」はログインシェルとして起動する。

また、`ssh` コマンドで `ssh user@remote-host /path/command` のようにコマンドを実行する場合は、インタラクティブシェルではない。

**確認手順:**

```sh
# ログインシェルか？
$ [[ -o login ]] && echo true || echo false

# インタラクティブシェルか？
$ [[ -o interactive ]] && echo true || echo false
```

上記では、シェルオプションに login や interactive を含むか評価している。

シェルオプションの一覧は、前述のとおり引数なしの `setopt` コマンドで確認できる。
なお、`shopt` コマンドは Bash の組み込みコマンドなので、zsh では使えない。

## zsh の設定ファイル

> cf. [zsh: 5 Files](http://zsh.sourceforge.net/Doc/Release/Files.html)
> cf. [Zsh/Bash startup files loading order (.bashrc, .zshrc etc.) | The Lumber Room](https://shreevatsa.wordpress.com/2008/03/30/zshbash-startup-files-loading-order-bashrc-zshrc-etc/)

基本的に `~/.zshrc` さえ覚えておけば OK。

設定は下表の上から順番に読み込まれる。
この時、各ファイルはそれぞれ**グローバル設定**（`/etc/` 配下）、**ローカル設定**（`~/` 配下）の順に読み込まれる。

| ファイル名  | ログイン<br>シェル | インタラクティブ<br>シェル | シェル<br>スクリプト | 用途                                                  |
| ----------- | :----------------: | :------------------------: | :------------------: | ----------------------------------------------------- |
| `.zshenv`   |         🔵         |             🔵             |          🔵          | 起動時に必ず読み込まれる。                            |
| `.zprofile` |         🔵         |             ❌             |          ❌          | ログイン時にのみ、`.zshrc` より前に読み込まれる。     |
| `.zshrc`    |         🔵         |             🔵             |          ❌          | 👑 メイン設定ファイル。                               |
| `.zlogin`   |         🔵         |             ❌             |          ❌          | ログイン時にのみ、`.zshrc` より後に読み込まれる。     |
| `.zlogout`  |         🔵         |             ❌             |          ❌          | ログアウト時（`exit` / `logout`）にのみ読み込まれる。 |

**補足:**

- グローバル設定のファイル名は、`.` を含まない。
    - e.g. `/etc/zshenv`
- ローカル設定は、環境変数 `ZDOTDIR` が定義されていればこちらを優先する。
    未定義の場合のみ、環境変数 `HOME` = `~` のパス配下を参照する。

# 付録: Bash との挙動の主な違い

- `history` コマンド
    - デフォルトだと直近 16 件しか表示されない。すべて表示するには `history 1`。
    - 履歴を削除したい場合は `vi $HISTFILE` などで編集する。
        - cf. [How to remove an entry from the history in ZSH - Stack Overflow](https://stackoverflow.com/questions/7243983/how-to-remove-an-entry-from-the-history-in-zsh)
- 単語区切り
    - 単語区切りのための環境変数 `WORDCHARS` のせい（？）

# 参考文献

- [bash と zsh の違い。bash からの乗り換えで気をつけるべき 16 の事柄](https://kanasys.com/tech/803#index1-0)
- [Zsh 変数メモ](https://gist.github.com/sho-t/d9cdf8271b3de7c4238739e523490542)
- [Zsh - ArchWiki](https://wiki.archlinux.jp/index.php/Zsh)
- [よく使うキー操作（Emacs キーバインドの場合）](https://qiita.com/uasi/items/c4288dd835a65eb9d709#%E3%82%88%E3%81%8F%E4%BD%BF%E3%81%86%E3%82%AD%E3%83%BC%E6%93%8D%E4%BD%9Cemacs-%E3%82%AD%E3%83%BC%E3%83%90%E3%82%A4%E3%83%B3%E3%83%89%E3%81%AE%E5%A0%B4%E5%90%88)
- [.zshrc を色んな環境で共有する方法を考えてみた - Qiita](https://qiita.com/catatsuy/items/00ebf78f56960b6d43c2)
- [コマンドライン編集機能 Zsh Line Editor を使いこなす - Qiita](https://qiita.com/b4b4r07/items/8db0257d2e6f6b19ecb9)
- [zsh で cd の履歴管理に標準添付の cdr を使う - @znz blog](https://blog.n-z.jp/blog/2013-11-12-zsh-cdr.html)
- [zsh とか便利コマンドあれこれ](https://blog.freedom-man.com/zsh-command)