ドットファイルの install/uninstall スクリプトの作成
クラウドを利用したドットファイルの共有
複数の環境(パソコン)間でドットファイルを共有するために,クラウドを利用すると便利である.
このため,最近,ドットファイルの管理にクラウドを導入した.
また,クラウド環境として自分はGitHubを採用した.
ドットファイルの install スクリプトの作成
インストールの手間を短縮
新しい環境を使い始める際や既存の環境をリセットした際の, ドットファイルをインストールする手間を短縮したい. このため,今回はインストールスクリプトを作成する.
インストールスクリプトの設計方針
GitHubで知り合いのリポジトリを漁っていると,以下のコードが釣れた.
#!/bin/bash for f in .??* do [[ "$f" == ".git" ]] && continue [[ "$f" == ".DS_Store" ]] && continue ln -s $HOME/dotfiles/$f $HOME/$f done
上記コードはホームディレクトリにドットファイルのリンクを貼るスクリプトである.このコードを拡張し,インストールスクリプトを作成することにした.
達成したい課題
- MacとWSL(Windows)で実行可能
現状,MacとWSLのターミナルを使っているので, どちらからでも実行できるようにする. - MacとWSLでインストールするドットファイルを変更
ターミナルが異なる場合,共有したいドットファイルもあれば,共有したくない(異なる環境設定にしたい)ものもある. このため,異なるターミナル,今回はMacとWSLでインストールするドットファイルを変更する. - リンクが貼れない状況に対応
貼りたいドットファイルと同名のファイルが既にホームディレクトリに存在する場合,$ ln
コマンドにエラーを出力させず,自分が設定した文字列を出力する(エラー処理).
各課題への対処
MacとWSL(Windows)で実行可能
Macで実行できたコードがWSLで動かない,といったことは何度もあったが,正直,原因がよくわからなかった. 色々試した結果,以下の3点を行うことでうまく動いた.
function
を使わない.
WSLの方でエラーを吐かれた.このため,function
を使わず,代わりに別ファイルを作成し,そのファイル(スクリプト)を呼び出すことにした.- bashではなく,shで実行する.
shebangをbashからshに変えるだけでなく,以下の様に実行コマンドもsh
を使う.
$ sh ./install.sh
- 条件式に
[[
を使わず,全て[
を使う.
[[
はbashのコマンドらしいので,[
に変更する.
MacとWSLでインストールするドットファイルを変更
以下の方法で対処する.
以下のコードで実行OS(ターミナル)を判断し,ホームディレクトリに共有ドットファイルと専用ドットファイルのリンクを貼る.
#!/bin/sh # OS(ターミナル)の種類を判断 if [ "$(uname)" = 'Darwin' ]; then OS='Mac' elif [ $(echo $(uname -r) | grep -e 'Microsoft') ]; then OS='WSL' else echo "Your platform ($(uname -a)) is not supported." OS='undefined' fi echo $OS' terminal\n' # 各OS(ターミナル)に応じて dotfile のリンクを貼る. if [ ! $OS = "undefined" ]; then sh scripts/link_dotfiles_to_home.sh $OS"/" fi # 各OS(ターミナル)共通の dotfile のリンクを貼る. sh scripts/link_dotfiles_to_home.sh ""
また,link_dotfiles_to_home.sh
は指定したディレクトリ下のドットファイルのリンクをホームディレクトリに貼るスクリプトである.
第一引数でそのディレクトリを指定する.
これは参考コードのfor f in .??*
をfor f in $1.??*
に改変することで実現した.
リンクが貼れない状況に対応
以下の状況を条件文により分岐し,処理.
- 既にファイルがある場合
[NG] を出力 - 既にリンクがある場合
[skip] を出力 - それ以外(リンクが貼れる場合)
リンクを貼り,[OK] を出力
また,各[NG], [skip] および [OK] のecho
出力には色を付けた.
link_dotfiles_to_home.sh
のソースコードは以下の通り.
#!/bin/sh for f in $1.??* do # ファイルの絶対パスを取得 dotfile_path=$HOME"/dotfiles/"$f # ファイルパスの一番右の"/"以降の文字列を取得 dotfile_name=${dotfile_path##*/} # 特定のファイルは pass [ "$dotfile_name" = ".git" ] && continue [ "$dotfile_name" = ".gitignore" ] && continue [ "$dotfile_name" = ".DS_Store" ] && continue # ファイルのリンクが既に貼られていれば skip を出力 if [ -h $HOME"/"$dotfile_name ]; then echo "[\033[36mskip\033[0m] "$dotfile_name # ファイルの実体(!=リンク)があれば,NG を出力 elif [ -e $HOME"/"$dotfile_name ]; then echo "[\033[31mNG\033[0m] "$dotfile_name # ファイルのリンクが貼られていなければ,シンボリックリンクを貼る. else ln -s $dotfile_path $HOME"/"$dotfile_name echo "[\033[32mOK\033[0m] "$dotfile_name fi done
install スクリプトの実行による出力は以下の通り.
uninstall スクリプトの作成
処理内容はほぼ install スクリプトと同じで,作成されたリンクをアンリンクするだけ.
具体的に,link_dotfiles_to_home.sh
のソースの一部を以下のコードに改変し,delete_symbolic_links.sh
として保存する.
uninstall.sh
はinstall.sh
のlink_dotfiles_to_home.sh
を呼ぶコードをdelete_symbolic_links.sh
を呼ぶコードに変えるだけ.
#!/bin/sh for f in $1.??* do # ファイルの絶対パスを取得 dotfile_path=$HOME/dotfiles/$f # ファイルパスの一番右の"/"以降の文字列を取得 dotfile_name=${dotfile_path##*/} # 特定のファイルは pass [ "$dotfile_name" = ".git" ] && continue [ "$dotfile_name" = ".gitignore" ] && continue [ "$dotfile_name" = ".DS_Store" ] && continue # ファイルのリンクが既に貼られていれば,ホームディレクトリのリンクを削除 if [ -h $HOME"/"$dotfile_name ]; then unlink $HOME"/"$dotfile_name echo "[\033[32mOK\033[0m] "$dotfile_name # ファイルの実体(!=リンク)があれば,NG を出力 elif [ -e $HOME"/"$dotfile_name ]; then echo "[\033[31mNG\033[0m] "$dotfile_name # ファイルのリンクが貼られていなければ skip else echo "[\033[36mskip\033[0m] "$dotfile_name fi done