ワンライナーでdotfilesをインストールする

ワンライナーでdotfilesを設定するとはどういうことなのか簡単に説明すると

bash -c "$(curl -fsSL https://raw.githubusercontent.com/kisqragi/dotfiles/master/install.sh)"

上記のコマンドを実行するだけで.vimrcや.bashrcなどの設定ファイルがインストールされるということです。

中には上記のコマンドをさらに簡単にして、githubのURLではなく自身のドメインにすることでコマンドを短くする方法を取っている方もいました。
ですが今回はその方法はとらず、とりあえずワンライナーでインストールが行えることを目標に頑張ります。

curl -sL dot.hoge.com | sh で自分専用環境を構築する方法(かっこいい) - 若くない何かの悩み

ドメインを用いた管理法について興味のある方は上記を参考にしていただければと思います。

dotfiles

現在の私のディレクトリを載せておきます。

github.com

はじめに

まずはじめに管理するdotfilesがなければ意味がありません。

dotfilesを管理しよう - Qiita

上記のサイトを参考に自身が管理するdotfileをgithub上にupしましょう。

簡単にコマンド群だけ載せておきます。

mkdir ~/dotfiles
cd ~/dotfiles
git init
echo "#dotfiles" > README.md
git add .
git commit -m "first commit"
~ github上でリポジトリ作成 ~
git remote add <URL>
git push origin master

あとは上記で作ったディレクトリに.vimrcなどを追加していけば良いです。

install.shの作成

bashスクリプトでinstall.shというインストール用のスクリプトを書きます。

基本形の作成

#!/bin/bash

DOT_DIR="$HOME/dotfiles"
for f in *;
do
    [[ "$f" == ".git" ]] && continue
    [[ "$f" == ".gitignore" ]] && continue
    [[ "$f" == ".DS_Store" ]] && continue
    [[ "$f" == "README.md" ]] && continue
    [[ "$f" == "install.sh" ]] && continue

    ln -snf $DOT_DIR/"$f" $HOME/".$f"
    echo "Installed .$f"
done

これが基本形です。
for文で現在ディレクトリのファイルを取得し変数fに格納します。
それを.ファイル名という形に変換してシンボリックリンク を貼ります。
コピーではなくリンクを貼ることで編集後にpushするのが楽になります。
ちなみに私はgithub.vimrcではなくvimrcというファイル名で管理しているのでドットファイルに変換していますが、.vimrcというファイルで管理する場合は変換の必要はありません。
$HOME/".$f"ではなく$HOME/$fで大丈夫です。
あと$HOMEではなく~を使っても同じです。

[[ "$f" == "hoge" ]] && continueという文がいくつかありますが、これは不必要なファイルをドットファイルとして設定しないための処理です。
他にも設定しないファイルが出てきた際はhogeの部分を変えて処理を追加すれば良いです。

ファイルが既に存在する場合実行しないようにする

今度はdotfilesが既に存在する場合はインストール処理を行わないようにします。
既に存在する場合は別で管理するか、git pullで新バージョンを持ってくれば良いので。
存在するかどうかの判定処理を追加します。

#!/bin/bash
DOT_DIR="$HOME/dotfiles"
if if [ ! -d ${DOT_DIR} ]; then
    for f in *
    do
        [[ "$f" == ".git" ]] && continue
        [[ "$f" == ".gitignore" ]] && continue
        [[ "$f" == ".DS_Store" ]] && continue
        [[ "$f" == "README.md" ]] && continue
        [[ "$f" == "install.sh" ]] && continue

        ln -snf $DOT_DIR/"$f" $HOME/".$f"
        echo "Installed .$f"
    done
else
    echo "dotfiles already exists"
    exit 1
fi

追加したif if [ ! -d ${DOT_DIR} ]; thenの処理でディレクトリが存在していなければ内部処理に移るようにします。
存在した場合はメッセージを表示して終了します。

ファイルのダウンロードを行う

今までの処理はユーザディレクトリ以外の場所にdotfilesディレクトリがある場合を想定しての処理でした。
ですが新規にインストールする場合(OS再設定後など)ではそもそも管理しているdotfilesディレクトリをダウンロードしてくる必要があります。
その処理を追加します。

#!/bin/bash

DOT_DIR="$HOME/dotfiles"

has() {
    type "$1" > /dev/null 2>&1
}

if if [ ! -d ${DOT_DIR} ]; then
    if has "git"; then
        git clone https://github.com/kisqragi/dotfiles.git ${DOT_DIR}
    else
        echo "git required"
        exit 1
    fi
    cd ${DOT_DIR}
    for f in *
    do
        [[ "$f" == ".git" ]] && continue
        [[ "$f" == ".gitignore" ]] && continue
        [[ "$f" == ".DS_Store" ]] && continue
        [[ "$f" == "README.md" ]] && continue
        [[ "$f" == "install.sh" ]] && continue

        ln -snf $DOT_DIR/"$f" $HOME/".$f"
        echo "Installed .$f"
    done
else
    echo "dotfiles already exists"
    exit 1
fi

処理がいくつか増えたので一つずつ説明します。
まずは先頭に追加されたhas関数です。
これはコマンド名を受け取ってそのコマンドが存在するかどうかを判定する関数です。
これを利用してその後の処理ではgitコマンドが存在する場合処理をするよう判定しています。

if has "git"; then
    git clone https://github.com/kisqragi/dotfiles.git ${DOT_DIR}
else
    echo "git required"
    exit 1
fi

gitコマンドが存在すればホームディレクトリにdotfilesという名前でディレクトリをダウンロード。
なければメッセージを表示して終了という形にしています。
その後cdコマンドでdotfilesへ移動しています。cd ${DOT_DIR}
URLは自身のリポジトリのURLにしてください。

gitコマンド以外でインストールする

上記のスクリプトでももうワンライナーでインストールはできます。
ただそのままだとgitコマンドがインストールされていない環境では実行ができません。
なので搭載されている可能性の高い(?)curlwgetを用いたインストールの処理も追加します。

#!/bin/bash

DOT_DIR="$HOME/dotfiles"

has() {
    type "$1" > /dev/null 2>&1
}

if [ ! -d ${DOT_DIR} ]; then
    if has "git"; then
        git clone https://github.com/kisqragi/dotfiles.git ${DOT_DIR}
    elif has "curl" || has "wget"; then
        TARBALL="https://github.com/kisqragi/dotfiles/archive/master.tar.gz"
        if has "curl"; then
            curl -L ${TARBALL} -o master.tar.gz
        else
            wget ${TARBALL}
        fi
        tar -zxvf master.tar.gz
        rm -f master.tar.gz
        mv -f dotfiles-master "${DOT_DIR}"
    else
        echo "curl or wget or git required"
        exit 1
    fi

    cd ${DOT_DIR}
    for f in *;
    do
        [[ "$f" == ".git" ]] && continue
        [[ "$f" == ".gitignore" ]] && continue
        [[ "$f" == ".DS_Store" ]] && continue
        [[ "$f" == "README.md" ]] && continue
        [[ "$f" == "install.sh" ]] && continue

        ln -snf $DOT_DIR/"$f" $HOME/".$f"
        echo "Installed .$f"
    done
else
    echo "dotfiles already exists"
    exit 1
fi

これが今回の完成系になります。
大きく変わった部分を説明します。

elif has "curl" || has "wget"; then
    TARBALL="https://github.com/kisqragi/dotfiles/archive/master.tar.gz"
    if has "curl"; then
        curl -L ${TARBALL} -o master.tar.gz
    else
        wget ${TARBALL}
    fi
    tar -zxvf master.tar.gz
    rm -f master.tar.gz
    mv -f dotfiles-master "${DOT_DIR}"
else
    echo "curl or wget or git required"
    exit 1
fi

まずこの処理の流れとしてはcurlwget存在する方のコマンドで圧縮されたdotfilesをダウンロードします。
その後解凍し、圧縮ファイルの削除、解凍したディレクトリを名前を変えてホームディレクトリへ配置。となっています。
tarballというのはtar.gz拡張子のファイルのことをいいます。
tarballに設定するURLの取得方法ですがまずgithubリポジトリへ移動します。
Clone or downloadをクリック
Download Zipがあるので右クリックか何かでリンクのアドレスをコピーします。
するとまずzipファイルのURLが取得できます。
そしたら.zip拡張子を.tar.gzに変更するだけです。
https://github.com/kisqragi/dotfiles/archive/master.zip

https://github.com/kisqragi/dotfiles/archive/master.tar.gz
f:id:kisaragi211:20200217222153p:plain

zip拡張子のままダウンロードしてきてunzipで解凍しても良いのですがunzipがあってtarがないというパターンは少ないと思います(多分)
tarはあるけどunzipはないという環境の方が多い気がします。
なので今回はわざわざtar.gz拡張子で行っています。

全体ソース

改めて全体ソースを載せます。

#!/bin/bash

DOT_DIR="$HOME/dotfiles"

has() {
    type "$1" > /dev/null 2>&1
}

if [ ! -d ${DOT_DIR} ]; then
    if has "git"; then
        git clone https://github.com/kisqragi/dotfiles.git ${DOT_DIR}
    elif has "curl" || has "wget"; then
        TARBALL="https://github.com/kisqragi/dotfiles/archive/master.tar.gz"
        if has "curl"; then
            curl -L ${TARBALL} -o master.tar.gz
        else
            wget ${TARBALL}
        fi
        tar -zxvf master.tar.gz
        rm -f master.tar.gz
        mv -f dotfiles-master "${DOT_DIR}"
    else
        echo "curl or wget or git required"
        exit 1
    fi

    cd ${DOT_DIR}
    for f in *;
    do
        [[ "$f" == ".git" ]] && continue
        [[ "$f" == ".gitignore" ]] && continue
        [[ "$f" == ".DS_Store" ]] && continue
        [[ "$f" == "README.md" ]] && continue
        [[ "$f" == "install.sh" ]] && continue

        ln -snf $DOT_DIR/"$f" $HOME/".$f"
        echo "Installed .$f"
    done
else
    echo "dotfiles already exists"
    exit 1
fi

インストールコマンドをREADMEへ追加する

最後の締めとして、インストールを行うコマンドをREADMEへ追加します。
こうすることでリポジトリを開くとすぐにコピーが行えて楽になります。
READMEを編集して以下を追加します。

bash -c "$(curl -fsSL https://raw.githubusercontent.com/kisqragi/dotfiles/master/install.sh)"

curlの引数に指定するURLは自身のリポジトリを参照してください。
f:id:kisaragi211:20200217223534p:plain 今回作ったinstall.shのページを開きます。
そうするとソースコードの帯にRawというタブがあるのでそこをクリックします。
そのページのURLをコピーして使ってください。

まとめ

参考にさせていただいた方のページを最後の方に掲載しますので、わからない部分はそちらを参考にしていただければ良いと思います。

参考

dotfilesをGitHubで管理 - Qiita
優れた dotfiles を設計して、最速で環境構築する話 - Qiita
『GitHub+dotfiles』は環境構築を一瞬で終わらせるすごいやつ | vdeep