⚡️

dotfilesを作成し、Macの環境構築を一発でできるようにしてみた

2022/11/22に公開約9,800字

dotfilesとは

ホームディレクトリに存在するドット(.)から始まるファイルのことを総称して、dotfilesと言われています。

  • .zshrc
  • .vimrc
  • .gitconfig

要するに、設定ファイルのことです。

ただ、環境構築に必要な設定ファイルであれば、どのようなファイルでもdotfilesと呼ぶことが可能みたいです。

なので今回は、環境構築に必要な設定ファイルやスクリプトを作成し、dotfilesとしてまとめてみました。

GitHubに公開しているので、興味がある方は是非ご覧ください。
https://github.com/ryota-k0827/dotfiles

本記事では、自動セットアップの解説を行います。

フォルダ構成

私が作成したdotfilesのフォルダ構成は以下のようになっています。

~/dotfiles
dotfiles/
├── .bin
│   ├── .Brewfile
│   ├── .gitconfig
│   ├── .gitignore_global
│   ├── .inputrc
│   ├── .npmrc
│   ├── .vimrc
│   ├── .yarnrc
│   ├── .zprofile
│   ├── .zshrc
│   ├── brew.sh
│   ├── defaults.sh
│   ├── init.sh
│   ├── link.sh
│   ├── other_apps.sh
│   └── setup.sh
└── Makefile

自動セットアップの流れ

Makefileでshellスクリプトを実行

dotfilesのリポジトリをクローンし、Makeコマンドを実行するだけでシンボリックリンクを作成したり、brewで必要なパッケージをインストールしたり、macOSの設定を変更したり、その他brewでは入手できないツールのインストール、といった環境構築を一発で行えるようにしました。

Makefile
# Do everything.
all: init link defaults brew setup other_apps

# Set initial preference.
init:
	@echo "\033[0;34mRun init.sh\033[0m"
	@.bin/init.sh
	@echo "\033[0;34mDone.\033[0m"

# Link dotfiles.
link:
	@echo "\033[0;34mRun link.sh\033[0m"
	@.bin/link.sh
	@echo "\033[0;32mDone.\033[0m"

# Set macOS system preferences.
defaults:
	@echo "\033[0;34mRun defaults.sh\033[0m"
	@.bin/defaults.sh
	@echo "\033[0;32mDone.\033[0m"

# Install macOS applications.
brew:
	@echo "\033[0;34mRun brew.sh\033[0m"
	@.bin/brew.sh
	@echo "\033[0;32mDone.\033[0m"

# Setup tools.
setup:
	@echo "\033[0;34mRun setup.sh\033[0m"
	@.bin/setup.sh
	@echo "\033[0;32mDone.\033[0m"

# Setup Other apps
other_apps:
	@echo "\033[0;34mRun other_apps.sh\033[0m"
	@.bin/other_apps.sh
	@echo "\033[0;32mDone.\033[0m"

make allを実行すると、init.sh -> link.sh -> defaults.sh -> brew.sh -> setup.sh -> other_apps.shの順番で処理が走ります。

init.sh

Macの初期設定に必要なコマンドをまとめています。
私はM1 Macを使用しているので、Rosetta2のインストールとCommand Line Toolsのインストールを行っています。
homebrewのインストールもここで行っています。

init.sh
#!/bin/zsh

# Check operating system
if [ "$(uname)" != "Darwin" ] ; then
	echo "Not macOS!"
	exit 1
fi

# Install Rosetta 2 for Apple Silicon
if [ "$(uname -m)" = "arm64" ] ; then
  /usr/sbin/softwareupdate --install-rosetta --agree-to-license
fi

# Install xcode
xcode-select --install

# Install brew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
if [ "$(uname -m)" = "arm64" ] ; then
  eval "$(/opt/homebrew/bin/brew shellenv)" > /dev/null
fi

link.sh

シンボリックリンクを作成するスクリプトです。

link.sh
#!/bin/zsh

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

for dotfile in "${SCRIPT_DIR}"/.??* ; do
    [[ "$dotfile" == "${SCRIPT_DIR}/.git" ]] && continue
    [[ "$dotfile" == "${SCRIPT_DIR}/.github" ]] && continue
    [[ "$dotfile" == "${SCRIPT_DIR}/.DS_Store" ]] && continue

    ln -fnsv "$dotfile" "$HOME"
done

dotfiles配下には、シンボリックリンクを作成すべきでないファイルもあるので、それらを除外しています。
それ以外のドットファイルは、ホームディレクトリにシンボリックリンクを貼っています。

defaults.sh

macOSの設定を変更するスクリプトです。
defaultsコマンドはかなり奥が深いので、これからもっといろいろと設定を追加していきたいと思っています。

defaults.sh
#!/bin/zsh

if [ "$(uname)" != "Darwin" ] ; then
	echo "Not macOS!"
	exit 1
fi

# ====================
#
# Base
#
# ====================

# Remap the emoji picker to the Fn key
defaults write com.apple.HIToolbox AppleFnUsageType -int 2

# Enable full keyboard access for all controls
defaults write NSGlobalDomain AppleKeyboardUIMode -int 3

# Show files with all extensions
defaults write NSGlobalDomain AppleShowAllExtensions -bool true

# Always display scrollbars
defaults write NSGlobalDomain AppleShowScrollBars -string "Always"

# Use the Fn key as a standard function key
defaults write NSGlobalDomain com.apple.keyboard.fnState -bool true

# Key repeat speed
defaults write NSGlobalDomain KeyRepeat -int 2

# Disable auto-capitalization
defaults write NSGlobalDomain NSAutomaticCapitalizationEnabled -bool false

# Timing to start key repeat
defaults write NSGlobalDomain InitialKeyRepeat -int 25

# ====================
#
# DesktopServices
#
# ====================

# Do not create .DS_Store files on USB or network storage
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
defaults write com.apple.desktopservices DSDontWriteUSBStores -bool true

# ====================
#
# Dock
#
# ====================

# Disable waiting time before the Dock is displayed
defaults write com.apple.dock autohide-delay -float 0

# Disable animation at application launch
# defaults write com.apple.dock launchanim -bool false

# ====================
#
# Finder
#
# ====================


# Disable animation
# defaults write com.apple.finder DisableAllAnimations -bool true

# Show hidden files by default
defaults write com.apple.finder AppleShowAllFiles -bool true

# Show icons for hard drives, servers, and removable media on the desktop
defaults write com.apple.finder ShowExternalHardDrivesOnDesktop -bool true
defaults write com.apple.finder ShowHardDrivesOnDesktop -bool true
defaults write com.apple.finder ShowMountedServersOnDesktop -bool true
defaults write com.apple.finder ShowRemovableMediaOnDesktop -bool true

# Display the status bar
defaults write com.apple.finder ShowStatusBar -bool true

# Display the path bar
defaults write com.apple.finder ShowPathbar -bool true


# ====================
#
# SystemUIServer
#
# ====================

# Display date, day, and time in the menu bar
defaults write com.apple.menuextra.clock DateFormat -string 'EEE d MMM HH:mm'

# Display battery level in the menu bar
# defaults write com.apple.menuextra.battery ShowPercent -string "YES"

# ====================
#
# Terminal
#
# ====================

# Use UTF-8 only
defaults write com.apple.terminal StringEncodings -array 4

for app in "Dock" \
	"Finder" \
	"SystemUIServer"; do
	killall "${app}" &> /dev/null
done

brew.sh

brew bundleを実行するためのスクリプトです。
brewでインストールするアプリケーションは、Brewfileに記述しています。
Brewfileには、App Storeからインストールするものも含まれています。
そのため、brew bundleを実行する前に、App Storeにログインしているかを確認しています。

brew.sh
#!/bin/zsh

# Check operating system
if [ "$(uname)" != "Darwin" ] ; then
	echo "Not macOS!"
	exit 1
fi

function open_app_store {
  echo "Please login with your Apple ID"
  sleep 1; echo "Open the App Store."
  sleep 1; open -a App\ Store
}

function login_check {
  while true; do
    echo -n "$* [Y/n]: (default: n) "
    read ANS
    case $ANS in
      [Yy]*)
        return 0
        ;;
      *)
        open_app_store
        ;;
    esac
  done
}

open_app_store
if login_check "Did you login?"; then
  brew bundle --global
fi
Brewfile
cask_args appdir: "/Applications"

tap "heroku/brew"
tap "homebrew/bundle"
tap "homebrew/cask"
tap "homebrew/cask-versions"
tap "homebrew/core"
tap "sanemat/font"

brew "git"
brew "gitmoji"
brew "git-secrets"
brew "mas"
brew "ricty"
brew "shellcheck"
brew "tree"
brew "volta"
brew "wget"

cask "adobe-creative-cloud"
cask "alt-tab"
cask "appcleaner"
cask "asana"
cask "bettertouchtool"
cask "brave-browser"
cask "canva"
cask "cheatsheet"
cask "deepl"
cask "discord"
cask "docker"
cask "figma"
cask "firefox"
cask "google-chrome"
cask "google-drive"
cask "karabiner-elements"
cask "keyboardcleantool"
cask "raycast"
cask "microsoft-edge"
cask "ngrok"
cask "notion"
cask "postman"
cask "scroll-reverser"
cask "slack"
cask "sourcetree"
cask "the-unarchiver"
cask "utm"
cask "visual-studio-code"
cask "warp"
cask "zoom"

mas "Gapplin", id: 768053424
mas "GarageBand", id: 682658836
mas "Hidden Bar", id: 1452453066
mas "iMovie", id: 408981434
mas "Keynote", id: 409183694
mas "LINE", id: 539883307
mas "Microsoft Excel", id: 462058435
mas "Microsoft PowerPoint", id: 462062816
mas "Microsoft Remote Desktop", id: 1295203466
mas "Microsoft Word", id: 462054704
mas "Numbers", id: 409203825
mas "Pages", id: 409201541
mas "PicGIF Lite", id: 844918735
mas "RunCat", id: 1429033973
mas "Spark", id: 1176895641
mas "Todoist", id: 585829637
mas "Twitter", id: 1482454543

setup.sh

インストールしたツールの設定を行うスクリプトです。

setup.sh
#!/bin/zsh

# Volta Setup
echo -e "\033[0;34m- Volta Setup...\033[0m"
volta setup

# Ricty Font Setup
echo -e "\033[0;34m- Ricty Font Setup...\033[0m"
cp -f /opt/homebrew/opt/ricty/share/fonts/Ricty*.ttf ~/Library/Fonts/
fc-cache -vf

# GitHub SSH Setup
echo -e "\033[0;34m- GitHub SSH Setup...\033[0m"
SSH_KEY_PATH="$HOME/.ssh"
ssh-keygen -N '' -f ${SSH_KEY_PATH}/id_rsa
pbcopy < ${SSH_KEY_PATH}/id_rsa.pub
echo "SSH key copied to clipboard. Paste it into GitHub."
sleep 1; echo "Open the GitHub settings page:"
sleep 1; open https://github.com/settings/ssh/new

other_apps.sh

brewやApp Storeでインストールできないアプリケーションのインストールを行うスクリプトです。
URLから直接ダウンロードできるものは、curlでダウンロードし、それ以外(アップデート毎にURLが変わるものなど)はダウンロードサイトを開くようにしています。

other_apps.sh
#!/bin/zsh

function ask_yes_no {
  while true; do
    echo -n "$* [Y/n]: (default: y) "
    read ANS
    case $ANS in
      [Yy]* | "")
        return 0
        ;;
      [Nn]*)
        return 1
        ;;
    esac
  done
}

function app_dl_web {
  if ask_yes_no "Do you want to download $1?"; then
    sleep 1; echo "Download $1"
    sleep 1; open $2
  fi
}

function app_dl_curl {
  DL_PATH="$HOME/Downloads/$(basename $2)"
  if ask_yes_no "Do you want to download $1?"; then
    sleep 1; echo "Download $1"
    sleep 1; curl $2 --output $DL_PATH
    open $DL_PATH
  fi
}

# DisplayLink Manager
app_dl_web "DisplayLink Manager" https://www.synaptics.com/products/displaylink-graphics/downloads/macos

# Logi Options+
app_dl_curl "Logi Options+" https://download01.logi.com/web/ftp/pub/techsupport/optionsplus/logioptionsplus_installer.zip

まとめ

macのセットアップを行うことはあまり頻繁にないと思いますが、一度作ってしまえば、次回以降は簡単にセットアップできるのでおすすめです!
これから少しずつ改良していきたいと思います。
次はUbuntuにも汎用的に使えるようにしたいですね。

参考文献

以下の記事を参考にさせていただきました。ありがとうございます!
https://dev.classmethod.jp/articles/joined-mac-dotfiles-customize/#toc-3

GitHubで編集を提案

Discussion

ログインするとコメントできます