【初心者版】必要最小限のdotfilesを運用する

# 解説動画

https://www.youtube.com/watch?v=zqkQO6YT534

# はじめに

最近、dotfilesというものを知りました。

`vim`や`tmux`、`git`などの設定ファイルは`.`から始まります。
そのため、これら設定ファイルは`ドットファイル`と呼ばれることがあります。
そして、`dotfiles`はこのドットファイルを管理するためのリポジトリ・ディレクトリです。

このdotfilesリポジトリを作成してGitで管理することで、
新しい環境を作るときに、設定を位置からやり直す必要がなくなります。

しかし、Qiitaで人気の
[ようこそdotfilesの世界へ](https://qiita.com/yutakatay/items/c6c7584d9795799ee164)などは、かなりLinux・Unix・GitHubに詳しい上級者向けに感じます。

そこで今回は、できるだけ自分のような初心者でも理解できた簡単版のdotfilesを運用しようと思います。

[ganariyaのdotfiles](https://github.com/Ganariya/dotfiles)はこのリンクにあります。

# 分かりやすい動画

MITの[Dotfiles](https://hacker-tools.github.io/dotfiles/)という動画がDotfilesの説明としてとても分かりやすいです。
英語字幕が用意されているので、簡単に見ることができます。


# Dotfilesディレクトリを作る

まず、ホームディレクトリ以下にdotfilesディレクトリを作成します。

```bash
cd ~
mkdir dotfiles
cd dotfiles
git init
```

このように、dotfilesを作って、これをGit/GitHubで運用していきます。


# シンボリックリンク

様々なアプリの設定ファイルは、ホームディレクトリ直下にそのままおいてあります。
このようなホームディレクトリ直下にある`~/.vimrc`のドットファイルを、そのままGitでバージョン管理することができません。

かといって、この.vimrcをそのままdotfilesにうつして
`~/dotfiles/.vimrc`としてしまうと、Gitでバージョン管理はできますが
ホームディレクトリに.vimrcが無いので、Vimに読み込まれなくなってしまいます･･･

両方作って、毎回更新するのは非常に面倒です。

そこで、**シンボリックリンク**を使用します。

これは、簡単に言うと「影分身」のようなもので、プログラミングの用語ではポインタ、Windowsなら「ショートカット」みたいなものです。

まずは実践してみます。

```bash
cd Desktop

echo "This is a a.txt" > a.txt
```

上記を実行すると、a.txtが生成されて中身はThis is a txt.となっていますね＞＜

次にシンボリックリンクを作ってみます。

```bash
ln -s a.txt b.txt
ln -s オリジナルファイル シンボリックリンク（影分身、ポインタ）
```
１行目を打ち込むと、b.txtが生成されているはずです。

中身はa.txtと同じになっています。

ここで、lsコマンドを打ってみると

```bash

 ls -la | grep txt                                           
-rw-r--r--@   1 ganariya  staff       16  4 25 19:47 a.txt
lrwxr-xr-x    1 ganariya  staff        5  4 25 19:48 b.txt -> a.txt
```

上記のようになります。これを見ると
`b.txt->a.txt`のように、b.txtの実体はただのポインタのようなものであり、a.txtへの参照であるという事がわかります。

よって、`b.txt`をマウスで開いたりVimで開いたりすると
OSはこの参照先である`a.txt`をかわりに開いてくれます＞＜

b.txtはただの影分身というかポインタなので、b.txtを消してもa.txtには何も影響ありません。

一方、a.txtのほうを消してしまうと、b.txtが参照する先がなくなってしまいます。

```
rm a.txt
open b.txt
The file /Users/ganariya/Desktop/b.txt does not exist.
```

結局、シンボリックリンクはただのポインタであり、
シンボリックリンクのファイルやディレクトリを開こうとすると、内部で参照を行ってオリジナルファイルを開いてくれるわけですね＞＜


# dotfilesでのシンボリックリンク

dotfilesとホームディレクトリ、どちらでオリジナルファイルを置くかですが
これは**dotfiles内にオリジナルファイル**を置きます。
そして、ホームディレクトリにシンボリックリンクを置いて、dotfiles内のオリジナルファイルを参照します。

これは以下のコマンドで実現できます。

```bash
# dotfiles内にうつしてあげる
cd ~
cp ~/.vimrc ~/dotfiles/.vimrc
rm ~/.vimrc
cd ~
ln -s ~/dotfiles/.vimrc ~/.vimrc
```

上記のようにすることで、dotfiles内に.vimrcを移し替えて
その後、シンボリックリンクをホームディレクトリに向けて貼ることができます。

こうすることで、ホームディレクトリの.vimrcをVimが読み込もうとすると参照が働いて、
バージョン管理を行っているdotfiles内の.vimrcを読み込みます。

実体はdotfiles内にあるのが大事なイメージです。


# shファイルで自動化する

一回一回

- 管理したいドットから始まるファイル/ディレクトリファイル$f$を、dotfilesにコピー
- 元のファイルをホームディレクトリから削除
- dotfiles内にコピーしたものを、ホームディレクトリに向かってシンボリックリンクを貼る

という操作をやるのは大変です。
そこで、自動化するためにシェルスクリプトを使用します。
初めてという方は検索で調べてみてください。

```bash:install.sh
#!/usr/bin/env bash

# 未定義な変数があったら途中で終了する
set -u

# 今のディレクトリ
# dotfilesディレクトリに移動する
BASEDIR=$(dirname $0)
cd $BASEDIR

# dotfilesディレクトリにある、ドットから始まり2文字以上の名前のファイルに対して
for f in .??*; do
    [ "$f" = ".git" ] && continue
    [ "$f" = ".gitconfig.local.template" ] && continue
    [ "$f" = ".gitmodules" ] && continue

    # シンボリックリンクを貼る
    ln -snfv ${PWD}/"$f" ~/
done
```

上記は、dotfilesディレクトリにあるドットから始まるファイルやディレクトリのシンボリックリンクを、ホームディレクトリに向かって貼るシェルスクリプトです。

[こちらのサイト](http://vdeep.net/github-dotfiles)を参考にさせていただきました。

`ln -snfv ${PWD}/"$f" ~/`は
`$f`ファイルを、ホームディレクトリに対して

- シンボリックリンクを貼り
- 経過を表示しながら
- 上書きしつつシンボリックリンクをホームディレクトリに貼る

という操作です。

このファイルをdotfiles内に作ったら

```bash
chmod +x install.sh
./install.sh
```

として、実行すればシンボリックリンクを貼ってくれます。


ここまでやるとあとは新しい環境でもすぐに環境が作れます。
dotfilesをクローンして、install.shを実行すれば一気にシンボリックリンクを貼ることが出来ます。
かんたんに新環境を作ることが出来ました。

# Homebrew(Mac)を用いたアプリインストールの自動化

設定ファイルの他にも

- 普段使用するアプリ
- ターミナルの設定
- シェルのインストール

など多くやりたいことがあります。

そこで、他にもシェルスクリプトを用意して、これらを実行するだけですべて完了することを目指します。


```bash:install_brew.sh
#!/bin/bash

echo "installing homebrew..."
which brew >/dev/null 2>&1 || /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

echo "run brew doctor..."
which brew >/dev/null 2>&1 && brew doctor

echo "run brew update..."
which brew >/dev/null 2>&1 && brew update

echo "ok. run brew upgrade..."
brew upgrade


formulas=(
    asciinema
    bat
    ctop
    dat
    exa
    ffmpeg
    fd
    fish
    gh
    git
    gitui
    jrnl
    mas
    mysql
    navi
    nb
    neovim
    neofetch
    nodebrew
    nnn
    pandoc
    procs
    poppler
    pstree
    sampler
    sd
    sqlite
    starship
    taskell
    thefuck
    tldr
    tmux
    tmuxinator
    tree
    warp
    yarn
)

echo "brew tap"
# brew tap thirdparty
brew tap homebrew/cask-fonts

echo "brew install formula"
for formula in "${formulas[@]}"; do
	brew install $formula || brew upgrade $formula
done

# install gui up
casks=(
    atom
    alfred
    alacritty
    appcleaner
    biscuit
    bitwarden
    boostnote
    cacher
    cheatsheet
    dash
    deepl
    discord
    docker
    drawio
    dropbox
    font-hack-nerd-font
    gitkraken
    grammarly
    google-backup-and-sync
    gyazo
    hyperswitch
    inkscape
    iterm2
    julia
    jetbrains-toolbox
    kap
    karabiner-elements
    keycastr
    mamp
    notion
    obs
    papers
    r
    rectangle
    skitch
    skype
    slack
    spotify
    steam
    tickeys
    visual-studio
    visual-studio-code
    vrew
    vlc
    xmind
    zoom
)

echo "brew casks"
for cask in "${casks[@]}"; do
	brew install --cask $cask
done


stores=(
    497799835
    539883307
    937984704
    975890633
    1144071713
    1295203466
    1423210932
    1429033973
    1450950860
    1483764819
)


echo "app stores"
for store in "${stores[@]}"; do
    mas install $store
done


brew cleanup

echo "brew installed"

```

[こちらのサイト](http://vdeep.net/github-dotfiles)を参考にさせていただきました。

homebrewをインストールして、必要なコマンドライン系のツールとcaskでアプリをインストールします。
これで一つ一つ検索してインストールする必要がありません。


# シェルやTexのインストール

[ganariya-dotfiles](https://github.com/Ganariya/dotfiles)では、
fishシェルの導入やフォントのインストールのシェルスクリプトも書いています。
参考にしてみてください。

# 最後に

簡易版のdotfilesを見てきました。
自分は普段fishを使っているので、bashに慣れておらずシェルスクリプトがとても難しいです･･･