【初学者殺し】fishシェルでPATHを通してみる

# はじめに
プログラミングを始めてから1年半、シェルはずっと`zsh`を使っていたのですが、知り合いにオススメされて`fish`デビューしました。

**fishってどんなヤツなん？使ったらどんないいことあるん？**ってのは、他の記事にたくさんまとまっているので、そちらを参考にしてください！

- [fish shellが結構良かった話 - Qiita](https://qiita.com/hennin/items/33758226a0de8c963ddf)
- [全訳！fishシェル普及計画](http://fish.rubikitch.com/)
- [ログインShellをfishにして作業効率を改善する](https://www.aizulab.com/blog/fish-shell/)

## 初学者殺しの「PATHを通す」
**初学者殺し**でおなじみ「PATHを通す」について、`fish`でも`bash`や`zsh`と同じように`~/.config/fish/config.fish`に設定を書くことで実現できるのですが、`fish`には`fish_user_paths`というユニバーサル変数（全てのセッションで共通の変数）を使うことでPATHを通すことができるようなので、そちらの方法でやってみます。


# fish_user_pathsって何？なぜ使う？

[fish shellのPATH設定 - Qiita](https://qiita.com/ledsun/items/8ca1a450b21c8ebc9670) に詳しく書かれておりますので、気になる方はご確認くださいませ。
（この後出てくる`set`コマンドのオプションについては[fishパス関連設定した時の備忘録](https://qiita.com/mecaota/items/43897896a429687f63aa)でまとめられています。）

# PATHを設定してみる

ユニバーサル変数 `fish_user_paths` に通したいPATHをセットし、PATHを通します。（同じこと2回言ってる...？）

## PATH と fish_user_pathsの中身を見てみる

まずは、中身を見てみます！

```bash:PATHの中身を表示

$ echo $PATH  //PATHの頭に"$"をつけることで、中身を表示することができる。他の環境変数も同様。

/usr/local/bin /usr/bin /bin /usr/sbin /sbin /Library/Apple/usr/bin
```

```bash:fish_user_pathsの中身を表示

$ echo $fish_user_paths　//PATHと同様に、fish_user_pathsの頭に"$"をつけることで、中身を表示することができる。

（何も出力されない）
```

たぶん初期設定ママだとこうなると思います。（この通りにならなくても気にせず先へ進みましょう！）

## fish_user_paths に追加してみる

今回は、
「`zsh`時代に使っていた`anyenv`コマンドが`fish`シェルに変えたら使えなくなった（= **PATHが通っていない**）」
という状況を想定して考えてみます。

たとえば、PATHを通すために`.zshrc`に`export PATH=$HOME/.anyenv/bin:$PATH` と書いていたなら、`$HOME/.anyenv/bin`が追加対象になります。

追加するときは、`set`コマンドに、`-U`のオプションをつけてあげます。（-Uのオプションをつけることで永続化できます）

```bash:fish_user_pathsに追加

$ set -U fish_user_paths $HOME/.anyenv/bin $fish_user_paths
$ echo $fish_user_paths

/Users/(ユーザー名)/.anyenv/bin 　←（ユーザー名） にはみなさんのPCのユーザー名が入ります
```

`fish_user_paths` に `/Users/(ユーザー名)/.anyenv/bin`が追加されたかと思います。


ちなみに、

```bash:HOMEの内容を表示
$ echo $HOME

/Users/(ユーザー名)
```

なので、さっきのやつは

```bash:fish_user_pathsに追加

$ set -U fish_user_paths /Users/(ユーザー名)/.anyenv/bin $fish_user_paths
$ echo $fish_user_paths

/Users/(ユーザー名)/.anyenv/bin
```

でも同じ結果になります。


では、PATHの中身を確認してみましょう。

```bash:PATHの中身を表示

$ echo $PATH

/Users/(ユーザー名)/.anyenv/bin /usr/local/bin /usr/bin /bin /usr/sbin /sbin /Library/Apple/usr/bin
```

初期設定で持っていたものに、今回`fish_user_paths`に追加したものが追加されています。

これで、`anyenv`コマンドがこれまで通り使えるようになりました。

つまり、`PATH`にもともと入っていた

```
/usr/local/bin /usr/bin /bin /usr/sbin /sbin /Library/Apple/usr/bin
```

に、`fish_user_paths`の内容を加えたものが`PATH`となります。

### 豆知識

`  | tr  ' ' '\n' | nl`をつけて出力すると、イイ感じに見やすくなります。

```bash:スペースで改行し、ナンバリングしてfish_user_pathsの中身を表示

$ echo $fish_user_paths  | tr  ' ' '\n' | nl

1 /Users/(ユーザー名)/.anyenv/bin
```

```bash:スペースで改行し、ナンバリングしてPATHの中身を表示

$ echo $PATH  | tr  ' ' '\n' | nl

1 /Users/(ユーザー名)/.anyenv/bin
2 /usr/local/bin
3 /usr/bin
4 /bin
5 /usr/sbin
6 /sbin
7 /Library/Apple/usr/bin
```


## fish_user_pathsから任意のパスを削除する

`fish_user_paths`は配列なので、特定のパスを削除する場合はインデックスを指定して削除する（**インデックスは０ではなく１から始まるので注意**）

まずは中身を確認して

```bash:インデックスを指定して、特定のfish_user_pathsを出力
$ echo $fish_user_paths[1]

/Users/(ユーザー名)/.anyenv/bin
```

`/Users/(ユーザー名)/.anyenv/bin`を消してみます。消す時は、`set`コマンドのオプションに`-e`をつけます。

```bash:インデックスを指定して、特定のfish_user_pathsを消す
$ set -e fish_user_paths[1]
$ echo $fish_user_paths

（何も出力されない）
```

はい、消えました。

ここでのポイントは、`set -e fish_user_paths[1]`で、`fish_user_paths[1]`の頭に`$`がついていないことです。`$`をつけるとエラーになります。

追加するときも、第一引数の環境変数(`fish_user_paths`)には`$`がついていませんね。

```bash
$ set -U fish_user_paths $HOME/.anyenv/bin $fish_user_paths
```

`$`はあくまで、内容を表示するときにつけます。

## fish_user_pathsの中身を全部削除する

ちなみに、`set -e fish_user_paths[1]`では「`fish_user_path`配列の1番目の要素を消す」でしたが、`set -e fish_user_paths`とインデックスを指定しない場合は全部一気に消えます。

```bash:インデックスを指定せず、fish_user_pathsの中身を全部消す
$ echo $fish_user_paths

1 /Users/(ユーザー名)/.anyenv/envs/nodenv/shims
2 /Users/(ユーザー名)/.anyenv/bin
3 /Users/(ユーザー名)/.rbenv/shims

（たとえば、fish_user_pathsに３つ入ってる状態）

$ set -e fish_user_paths
$ echo $fish_user_paths

（何も出力されない）
```

# まとめ

これまで「PATHを通す」時は、記事を見て言われるがままに`export PATH=$HOME/.anyenv/bin:$PATH`みたく設定をコピペし、「何だか分からないけど動くようになった...」というレベルだった自分ですが、今回のやり方を通じて「環境変数`PATH`に値をセットすることでPATHを通す」ということがようやく少し理解できました。

「シェルに詳しいわけではないけれどfishを使い始めた（これから使いたい）！」という人のお役に立てたら幸いです。

# 参考

- [fish shellが結構良かった話 - Qiita](https://qiita.com/hennin/items/33758226a0de8c963ddf)
- [全訳！fishシェル普及計画](http://fish.rubikitch.com/)
- [ログインShellをfishにして作業効率を改善する](https://www.aizulab.com/blog/fish-shell/)
- [fish shellのPATH設定 - Qiita](https://qiita.com/ledsun/items/8ca1a450b21c8ebc9670)
- [fishパス関連設定した時の備忘録 - Qiita](https://qiita.com/mecaota/items/43897896a429687f63aa)