記憶喪失のターミナルを天才に育てる魔法の呪文
ターミナルは記憶喪失?
「さーて、昨日やってたあのプロジェクトの続きをやるか!」
新しいターミナルを開くと、いつも出迎えてくれるのはホームディレクトリ (~/)。
そこから cd path/to/my/super/awesome-project/src/and/so/on のような長い道のりを、毎日毎日、律儀にタイプしていませんか?
まるでターミナルが毎朝きっかり記憶喪失になっているかのようです。
「昨日どこまで進めたか、覚えていてくれたらいいのに…」
そんなあなたのための、たった数行の魔法の呪文(スクリプト)をご紹介します。
記憶力を取り戻す呪文(初級編)
まずは小手調べ。この呪文をあなたの ~/.bashrc や ~/.zshrc の末尾に貼り付けてみてください。ターミナルが最後にいた場所を健気に覚えてくれるようになります。
# 記憶喪失のターミナルに「最後の場所」を思い出させる呪文
# コマンド実行直前に、現在の場所をこっそりメモさせる
PROMPT_COMMAND='pwd > ~/.last_dir'
# ターミナル起動時、前回のメモを読んでその場所にワープする
if [ -f ~/.last_dir ]; then
cd "$(cat ~/.last_dir)"
fi
天才に育てる呪文(上級編):記憶の迷宮へ、いざ出発
これを ~/.bashrc や ~/.zshrc に唱えれば、ターミナルを開くたびに、過去の冒険の軌跡(ディレクトリ履歴)をリストアップし、どこへでも一瞬でワープできるようになります。
さらに! 今回は特別に、複数の場所に同時にワープできる「複数選択機能」を追加しました! まるで忍者のように、複数の隠れ家を使いこなしましょう!
# 履歴ファイルの設定
DIR_HISTORY_FILE=~/.dir_history
# 記憶するディレクトリの最大数
MAX_HISTORY_SIZE=10
# コマンド実行直前に実行される関数を定義
_save_current_dir() {
local current_dir="$(pwd)"
local history=()
local unique_history=""
# 履歴ファイルを読み込み、配列に格納
if [ -f "$DIR_HISTORY_FILE" ]; then
IFS=$'\n' read -r -d '' -a history < "$DIR_HISTORY_FILE"
fi
# 配列の先頭に現在のディレクトリを追加
history=("$current_dir" "${history[@]}")
# 重複を除去し、最新のMAX_HISTORY_SIZE件に絞る
# (最新のディレクトリが先頭に来るため、この順で処理)
declare -A seen
for dir in "${history[@]}"; do
if [ -z "${seen[$dir]}" ]; then
unique_history="$unique_history$dir\n"
seen["$dir"]=1
fi
done
# ファイルに書き戻す(最新MAX_HISTORY_SIZE件のみ)
echo -e "$unique_history" | head -n $MAX_HISTORY_SIZE > "$DIR_HISTORY_FILE"
}
# PROMPT_COMMANDに記憶関数を登録
PROMPT_COMMAND='_save_current_dir'
# ターミナル起動時の処理(選択・移動)
if [ -f "$DIR_HISTORY_FILE" ]; then
echo -e "\n**🚀 以前のディレクトリ履歴:**"
# 履歴ファイルの内容を配列に読み込む
# IFS=$'\n'を設定し、改行でのみ区切るようにする
# read -d '' を使用して、ヌル文字まで(またはファイル全体)を読み込む
IFS=$'\n' read -r -d '' -a DIR_OPTIONS < "$DIR_HISTORY_FILE"
# 最後の選択肢(現在の場所にとどまる)を追加
DIR_OPTIONS+=("現在の場所にとどまる")
# selectに配列を渡す
select dir in "${DIR_OPTIONS[@]}"; do
if [ "$dir" == "現在の場所にとどまる" ] || [ -z "$dir" ]; then
echo "移動しませんでした。"
break
elif [ -d "$dir" ]; then
# 選択されたディレクトリへ移動
cd "$dir"
echo "➡️ **$dir** へ移動しました。"
break
else
# このエラーメッセージは通常出なくなるはずです
echo "無効な選択です。再度選択してください。"
fi
done
echo "" # 改行を追加してプロンプトを見やすくする
fi
パフォーマンスも考慮したさらなる進化した呪文
「毎回勝手に移動されるのはちょっと...」 「履歴が増えすぎてディスクが重くなるのは嫌だ!」
そんなわがままな(もとい、こだわり派の)あなたには、こちらの上級者向け呪文を授けましょう。
この呪文は以下の点で進化しています:
- ディスクへの優しさ (I/O最適化): 履歴の読み書きを最小限に抑え、SSDの寿命を延ばします(たぶん)。
- 整理整頓 (重複排除): 同じディレクトリが履歴に何度も登場するのを防ぎます。スマートですね。
- 自由意志の尊重 (
jコマンド): ターミナル起動時に勝手に移動しません。移動したい時はjと唱えるだけ。
Linux版
# 履歴ファイルの設定
DIR_HISTORY_FILE=~/.dir_history
MAX_HISTORY_SIZE=20
_save_current_dir_optimized() {
local current_dir="$(pwd)"
local history=()
local unique_history=""
local count=0
# 1. 履歴ファイルを読み込み
if [ -f "$DIR_HISTORY_FILE" ]; then
# 配列に読み込む(改行区切り)
IFS=$'\n' read -r -d '' -a history < "$DIR_HISTORY_FILE"
fi
# 2. 最新のディレクトリを先頭に追加し、重複を除去しながら配列を作成
declare -A seen
for dir in "$current_dir" "${history[@]}"; do
# 最大数に達したら終了
if [ "$count" -ge "$MAX_HISTORY_SIZE" ]; then
break
fi
if [ -z "${seen[$dir]}" ]; then
unique_history="$unique_history$dir\n"
seen["$dir"]=1
count=$((count + 1))
fi
done
# 3. ファイルに書き戻す (1回のI/O操作に集約)
echo -e "$unique_history" > "$DIR_HISTORY_FILE"
}
# PROMPT_COMMANDに軽量化された関数を登録
PROMPT_COMMAND='_save_current_dir_optimized'
# `j` コマンドでディレクトリ履歴を選択できるようにする関数 (上記スクリプトの後に追加)
j() {
if [ -f "$DIR_HISTORY_FILE" ]; then
echo -e "\n**🚀 ディレクトリ履歴:**"
IFS=$'\n' read -r -d '' -a DIR_OPTIONS < "$DIR_HISTORY_FILE"
DIR_OPTIONS+=("現在の場所にとどまる")
# fzf がインストールされていれば fzf を使用
if type fzf >/dev/null 2>&1; then
local selected_dir
selected_dir=$(printf '%s\n' "${DIR_OPTIONS[@]}" | fzf --prompt="Select Directory: " --height=~40% --layout=reverse --border)
if [ -n "$selected_dir" ] && [ "$selected_dir" != "現在の場所にとどまる" ]; then
cd "$selected_dir"
echo "➡️ **$selected_dir** へ移動しました。"
else
echo "移動しませんでした。"
fi
else
# fzf がなければ select を使用
select dir in "${DIR_OPTIONS[@]}"; do
if [ "$dir" == "現在の場所にとどまる" ] || [ -z "$dir" ]; then
echo "移動しませんでした。"
break
elif [ -d "$dir" ]; then
cd "$dir"
echo "➡️ **$dir** へ移動しました。"
break
else
echo "無効な選択です。再度選択してください。"
fi
done
fi
echo ""
else
echo "ディレクトリ履歴ファイルが見つかりません: $DIR_HISTORY_FILE"
fi
}
Mac版
# 履歴ファイルの設定
DIR_HISTORY_FILE=~/.dir_history
MAX_HISTORY_SIZE=20
_save_current_dir_optimized() {
# 空白を含むパスに対応するためクォートを徹底
local current_dir="$PWD"
local -a raw_history
local -a unique_history
# 1. 履歴の読み込み
if [ -f "$DIR_HISTORY_FILE" ]; then
# 改行区切りで配列に読み込む (zsh/bash両対応)
if [ -n "$ZSH_VERSION" ]; then
raw_history=("${(f)$(<"$DIR_HISTORY_FILE")}")
else
mapfile -t raw_history < "$DIR_HISTORY_FILE"
fi
fi
# 2. 重複除去ロジック (常に現在のディレクトリを先頭にする)
unique_history=("$current_dir")
for dir in "${raw_history[@]}"; do
# 空行、または現在のディレクトリと同じものはスキップ
if [ -z "$dir" ] || [ "$dir" = "$current_dir" ]; then
continue
fi
# 最大数に達するまで追加
if [ ${#unique_history[@]} -lt "$MAX_HISTORY_SIZE" ]; then
unique_history+=("$dir")
else
break
fi
done
# 3. ファイルへの書き出し (printfで1回で実行)
# 配列を改行で結合して出力
if [ ${#unique_history[@]} -gt 0 ]; then
printf "%s\n" "${unique_history[@]}" > "$DIR_HISTORY_FILE"
fi
}
# フックの登録
if [ -n "$ZSH_VERSION" ]; then
autoload -Uz add-zsh-hook
add-zsh-hook precmd _save_current_dir_optimized
else
# bash用: 重複登録を避けるため一度削除してから登録
PROMPT_COMMAND="${PROMPT_COMMAND%; _save_current_dir_optimized}"
PROMPT_COMMAND+="_save_current_dir_optimized"
fi
j() {
if [ ! -f "$DIR_HISTORY_FILE" ]; then
echo "ディレクトリ履歴が見つかりません。"
return
fi
local selected_dir
# 履歴を配列として読み込む
local options=(${(f)"$(cat "$DIR_HISTORY_FILE")"}) 2>/dev/null || \
IFS=$'\n' read -d '' -r -a options < "$DIR_HISTORY_FILE"
if type fzf >/dev/null 2>&1; then
selected_dir=$(printf '%s\n' "${options[@]}" | fzf --prompt="Go to: " --height=40% --reverse)
if [ -n "$selected_dir" ]; then
cd "$selected_dir" && ls
fi
else
# selectを使用する場合
PS3="移動先番号を選択 (qで終了): "
select opt in "${options[@]}"; do
if [ -n "$opt" ]; then
cd "$opt" && ls
break
else
break
fi
done
fi
}
使い方
- 上記のスクリプトを
.bashrcなどに追記し、source ~/.bashrcで読み込みます。 - ターミナルで作業します(履歴が溜まります)。
- 移動したくなったら、
jと打ってエンター!
$ j
**🚀 ディレクトリ履歴:**
1) /home/user/projects/awesome-app
2) /var/log
3) 現在の場所にとどまる
#?
数字を選べば、その場所にワープできます。
秘密のスパイス: fzf
もしあなたの環境に fzf (fuzzy finder) がインストールされていれば、この呪文は真の力を発揮します。
j コマンドを実行すると、リッチなインタラクティブ画面で履歴を検索・選択できるようになります。
これぞ、現代の魔法使いにふさわしいツールです。
ぜひ、インストールして試してみてください。世界が変わりますよ。