💻

Macの環境をdotfilesでセットアップしてみた改

2023/05/27に公開

以前以下のブログで公開したMac用のdotfilesを色々改良してみたので、改良版として本記事で公開する。

https://dev.classmethod.jp/articles/joined-mac-dotfiles-customize/

なおdotfilesとは、ホームディレクトリに存在するドット(.)から始まる設定ファイル群の事を指す。

dotfiles の中身

$ tree

.
├── .bin
│   ├── .Brewfile
│   ├── .bash_profile
│   ├── .bashrc
│   ├── .gitconfig
│   ├── .gitignore_global
│   ├── brew.sh
│   ├── defaults.sh
│   ├── init.sh
│   └── link.sh
├── .github
│   └── workflows
│       └── main.yml
├── Makefile
├── README.md
├── chrome
│   └── extensions
├── raycast
│   └── Raycast.rayconfig
└── vscode
    ├── extensions
    ├── settings.json
    └── sync.sh

dotfilesの詳細は、以下のGitHubのURLに上げている。

https://github.com/tsukuboshi/dotfiles

以下ではセットアップ用スクリプト、及びソフトウェア用設定ファイルに分けて解説する。

セットアップ用スクリプト

本項目では、Macにのdotfilesに格納されているファイルを用いてセットアップする際に使用するスクリプトについて説明する。

セットアップ自動化スクリプト(Makefile)

本dotfilesのルートディレクトリでmakeコマンドを叩く事で、Makefileに記載のあるスクリプトが全て実行され、セットアップを自動で実施する。

なおmake initmake linkmake defaultsmake brewコマンドにより、各々のスクリプト(init.sh, link.sh, brew.sh, defaults.sh)を個別で実行できる。

https://github.com/tsukuboshi/dotfiles/blob/main/Makefile

初期設定スクリプト(.bin/init.sh)

init.shは、Macで一番最初に実行するべき初期設定を実施する。

本dotfilesでは、zshからbashへの切り替え、及びXcodeとbrewのインストールを実行する。

https://github.com/tsukuboshi/dotfiles/blob/main/.bin/init.sh

シンボリックリンク作成スクリプト(.bin/link.sh)

link.shは、ホームディレクトリに対してドットから始める設定ファイルのシンボリックリンクを作成する。

なお.git.github.DS_storeといったシンボリックリンクの作成の必要がないファイルについては、あらかじめ除外する。

https://github.com/tsukuboshi/dotfiles/blob/main/.bin/link.sh

追加コマンド/アプリ導入スクリプト(.bin/brew.sh)

brew.shは、Macに追加で必要なコマンドツールやデスクトップアプリをインストールする。

追加で必要なコマンド及びアプリを.Brewfileに予め記載した上で、このスクリプトを実行すると一括インストールが可能。

https://github.com/tsukuboshi/dotfiles/blob/main/.bin/brew.sh

.Brewfileには、追加したいコマンド及びアプリを一覧で記載する。

https://github.com/tsukuboshi/dotfiles/blob/main/.bin/.Brewfile

Mac 環境設定スクリプト(.bin/defaults.sh)

defaults.shは、Mac自体の環境設定を操作する。

https://github.com/tsukuboshi/dotfiles/blob/main/.bin/defaults.sh

テスト自動化スクリプト(.github/workflows/main.yml)

main.ymlには、GitHub Actionsを用いて、Githubリポジトリにpushした際、自動で処理されるテストの内容を記載する。

本dotfilesではMacOSにおけるmakeコマンドのテストのみ実施しているが、他のコマンドを追記してテストする事も可能。

.github/workflows/main.yml
on:
  push:
    branches:
      - main

permissions:
  contents: read

jobs:
  make:
    runs-on: macos-latest

    defaults:
      run:
        shell: bash

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Dotfiles
        run: make

ソフトウェア設定ファイル

以下では、ソフトウェアの設定が記載されているファイルについて説明する。

Bash 設定ファイル(.bin/.bash_profile & .bin/.bashrc)

.bash_profile及び.bashrcには、ターミナルで使用するBashの設定が記載されている。

.bash_profileには、主に環境変数を設定するexportや、補完定義を設定するcomplete/souceを記載している。

https://github.com/tsukuboshi/dotfiles/blob/main/.bin/.bash_profile

対して、.bashrcには主にターミナルで用いるコマンド群を、引数を持たないaliasと、引数を持つfunctionに分けて記載している。

https://qiita.com/belion_freee/items/528ff57b920d559abf3d

なお.bash_profile.bashrcの使い分け方は好みの問題なので、どちらに記載しても構わない。

.bin/.bashrc
# User specific aliases and functions
# User specific aliases and functions
alias ll='ls -lF'
alias la='ls -lAF'

alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'

alias relogin='exec $SHELL -l'

alias checkip='curl inet-ip.info'

alias rmtrash='rm -rf ${HOME}/.Trash/*'

alias delds='find . -name ".DS_Store" -type f -ls -delete'

alias bl='brew list --formula'
alias bo='brew upgrade --dry-run'
alias bg='brew upgrade'

alias cl='brew list --cask'
alias co='brew upgrade --cask --greedy --dry-run'
alias cg='brew upgrade --cask --greedy'

alias ml='mas list'
alias mo='mas outdated'
alias mg='mas upgrade'

alias al='echo "************brew***************"; brew list --formula; echo "************cask***************"; brew list --cask; echo "************mas***************"; mas list'
alias ao='echo "************brew***************"; brew upgrade --dry-run; echo "************cask***************"; brew upgrade --cask --greedy --dry-run; echo "************mas***************"; mas outdated'
alias ag='echo "************brew***************"; brew upgrade; echo "************cask***************"; brew upgrade --cask --greedy; echo "************mas***************"; mas upgrade'

alias bbl='brew bundle list --global --all'
alias bbc='brew bundle check --global --formula'
alias bbi='brew bundle install --global'

alias gb='git branch --all'
alias gbl='git branch'
alias gbr='git branch --remote'
function gbd (){
  local LOCAL_BRANCH=$1
  git branch -D "${LOCAL_BRANCH}"
}

alias gs='git status'
function gf (){
  local REMOTE_BRANCH=${1:-HEAD}
  git fetch origin "${REMOTE_BRANCH}"
}
alias gfa='git fetch --all'
function gm (){
  local TRAKING_BRANCH=${1:-HEAD}
  git merge origin "${TRAKING_BRANCH}"
}
function gpl (){
  local REMOTE_BRANCH=${1:-`git branch --contains | cut -d " " -f 2`}
  git pull origin "${REMOTE_BRANCH}"
}
alias gpla='git pull --all'
alias gch="git checkout"
alias gcb="git checkout -b"
function gcbo (){
  local BRANCH=${1}
  git checkout -b ${BRANCH} origin/${BRANCH}
}
function ga (){
  local FILE=${1:-.}
  git add "${FILE}"
}
alias gax='git reset HEAD'
function gr (){
  local FILE=$1
  git rm "${FILE}"
}
function gcm (){
  local MESSAGE=${1:-fix}
  git commit -m "${MESSAGE}"
}
function gcma (){
  local MESSAGE=${1:-fix}
  git commit -m --amend "${MESSAGE}"
}
alias gcx='git reset --hard HEAD^'
function gps (){
  local REMOTE_BRANCH=${1:-HEAD}
  git push origin "${REMOTE_BRANCH}"
}
function gss (){
  local MESSAGE=$1
  git stash save "${MESSAGE}"
}
alias gsu='git stash save -u'
alias gsl='git stash list'
alias gsc='git stash clear'

alias pci='pre-commit install'
alias pcr='pre-commit run -a'
alias pcu='pre-commit autoupdate'

alias av='anyenv versions'
alias au='anyenv update'

alias nrb='npm run build'
alias nrw='npm run watch'
alias nrt='npm run test'
alias nig='npm install -g'
alias nid='npm install -D'
alias ncu='npx -p npm-check-updates  -c "ncu"'
alias ncuu='npx -p npm-check-updates  -c "ncu -u"'

function eap (){
  local PROFILE=${1:-tsukuboshi}
  export AWS_PROFILE=${PROFILE}
}
alias enap='export -n AWS_PROFILE'

function awsume (){
  local PROFILE=${1:-tsukuboshi}
  source $(pyenv which awsume) ${PROFILE}
}

alias asg='aws sts get-caller-identity'
alias asl='aws sso login'
function asl (){
  local PROFILE=$1
  aws sso login --profile ${PROFILE}
}
function ec2exec (){
  local INSTANCE_ID=$1
  aws ssm start-session --target ${INSTANCE_ID}
}
function ecsexec (){
  local CLUSTER_NAME=$1
  local TASK_ID=$2
  local CONTAINER_NAME=$3
  aws ecs execute-command --cluster ${CLUSTER_NAME} --task ${TASK_ID} --container ${CONTAINER_NAME} --interactive --command "/bin/sh"
}

alias samv='sam validate'
alias samb='sam build'
alias samp='sam deploy'
alias samd='sam destroy'

function cdkin (){
  local LANGUAGE=${1:-typescript}
  cdk init --language ${LANGUAGE}
}
alias cdks='cdk synthesize'
alias cdki='cdk diff'
alias cdkp='cdk deploy'
alias cdkl='cdk list'
alias cdkd='cdk destroy'

function tin (){
  local PROFILE=${1:-tsukuboshi}
  aws-vault exec ${PROFILE} -- terraform init
}
function tf (){
  local PROFILE=${1:-tsukuboshi}
  aws-vault exec ${PROFILE} -- terraform fmt -recursive
}
function tg (){
  local PROFILE=${1:-tsukuboshi}
  aws-vault exec ${PROFILE} -- terraform get
}
function tc (){
  local PROFILE=${1:-tsukuboshi}
  aws-vault exec ${PROFILE} -- terraform console
}
function tim (){
  local PROFILE=${1:-tsukuboshi}
  aws-vault exec ${PROFILE} -- terraform import
}
function tv (){
  local PROFILE=${1:-tsukuboshi}
  aws-vault exec ${PROFILE} -- terraform validate
}
function tp (){
  local PROFILE=${1:-tsukuboshi}
  aws-vault exec ${PROFILE} -- terraform plan
}
function ta (){
  local PROFILE=${1:-tsukuboshi}
  aws-vault exec ${PROFILE} -- terraform apply
}
function ts (){
  local PROFILE=${1:-tsukuboshi}
  aws-vault exec ${PROFILE} -- terraform state
}
function td (){
  local PROFILE=${1:-tsukuboshi}
  aws-vault exec ${PROFILE} -- terraform destroy
}
function tdoc (){
  local MODULE_PATH=${1:-.}
  terraform-docs markdown table --output-file README.md --output-mode inject ${MODULE_PATH}
}

function dib (){
  local IMAGE=${1:-itest}
  docker image build --platform linux/x86_64 -t ${IMAGE} .
}
alias dil='docker image ls -a'
alias dip='docker image prune'
function dcr (){
  local PORT=${1:-80}
  local IMAGE=${2:-itest}
  local CONTAINER=${3:-ctest}
  docker container run --platform linux/x86_64 --name ${CONTAINER} -d -p ${PORT}:80 ${IMAGE}
}
function dce (){
  local CONTAINER=${1:-ctest}
  docker container exec -it ${CONTAINER} bash
}
function dcs () {
  local CONTAINER=${1:-ctest}
  docker container stop $(docker container ls -a --filter="name=${CONTAINER}" --format="{{.ID}}")
}
function dcrm () {
  local CONTAINER=${1:-ctest}
  docker container rm $(docker container ls -a --filter="name=${CONTAINER}" --format="{{.ID}}")
}
alias dcl='docker container ls -a'
alias dcp='docker container prune'
alias dsp='docker system prune --volumes'
alias dcu='docker compose up -d'
alias dcd='docker compose down'

alias gle="ls -l ${HOME}/Library/Application\ Support/Google/Chrome/Default/Extensions | awk '{print \$9}' | sed 's/^/https:\/\/chrome.google.com\/webstore\/detail\//g' | sed -e '1,2d'"

alias cle='code --list-extensions'

function otp (){
  local ITEMID=${1:-AWS}
  if [ "$(which op)" != "" ]; then
    op item get ${ITEMID} --otp
  elif [ "$(which bw)" != "" ]; then
    bw get totp ${ITEMID}
  else
    echo  "Install the password manager command to get your totp."
  fi
}

Git 設定ファイル(.bin/.gitconfig & .bin/.gitignore_global)

.gitconfigには、Gitの設定が記載されている。

もしEメールがそのまま書かれている場合は、以下を参考にコミットメールアドレスを別で設定すると良い。

https://docs.github.com/ja/github-ae@latest/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-email-preferences/setting-your-commit-email-address

https://github.com/tsukuboshi/dotfiles/blob/main/.bin/.gitconfig

.gitignore_globalには、Gitによる追跡から除外するファイルが記載されている。

GitHub公式から、.gitignoreのテンプレートがサービス毎に提供されているので、参考にしながら自分用にカスタマイズすると良さげ。

https://github.com/github/gitignore

https://github.com/tsukuboshi/dotfiles/blob/main/.bin/.gitignore_global

Chrome 設定ファイル(chrome/配下)

extensionsにはChrome拡張機能のURLが記載されており、どのChrome拡張機能が導入されているかを一目で確認できる。

https://github.com/tsukuboshi/dotfiles/blob/main/chrome/extensions

ちなみに.bashrcに記載されている以下のコマンドで、現在Chromeに導入されている拡張機能のURLを上記のファイルのように一覧で出力できる。

.bashrc
alias gle="ls -l ${HOME}/Library/Application\ Support/Google/Chrome/Default/Extensions | awk '{print \$9}' | sed 's/^/https:\/\/chrome.google.com\/webstore\/detail\//g' | sed -e '1,2d'"

VSCode 設定ファイル(vscode/配下)

settings.jsonにはVSCode自体の設定が記載されている。

https://github.com/tsukuboshi/dotfiles/blob/main/vscode/settings.json

対してextensionには、VSCode拡張機能の名称が記載されており、どのvscode拡張機能が導入されているかを一目で確認できる。

https://github.com/tsukuboshi/dotfiles/blob/main/vscode/extensions

そしてsync.shを実行する事で、settings.jsonのシンボリックリンクの作成、及びextensionsに記載されている拡張機能のインストールを合わせて実施できる。

https://github.com/tsukuboshi/dotfiles/blob/main/vscode/sync.sh

ちなみに.bashrcに記載されている以下のコマンドで、現在VSCodeに導入されている拡張機能を上記のextensionsのように一覧で出力できる。

.bashrc
alias cle='code --list-extensions'

Raycast 設定ファイル(raycast/配下)

Raycast.rayconfigにはRaycastの設定が記載されており、RaycastのImport機能で取り込み可能。

(バイナリファイルのためファイル内容は記載しない)

Importのやり方は以下を参照。

https://www.raycast.com/changelog/1-22-0

dotfilesを始めよう

万が一自身のPCに何かが起きた際の設定のバックアップになるので、ぜひ簡単なdotfilesを作ってみてほしい。

またスクリプトを作成する事でBashを学べたり、GitHubリポジトリにバックアップとしてアップロードする事でGitの勉強にもなるので、エンジニア初心者がこの辺りの技術を学ぶにはちょうど良い教材な気もする。

(2024/3/28追記)
スクリプトの内容が見やすいよう、可能な限りファイルをGitHubの埋め込みに変更。

Discussion