ターミナルのディレクトリ移動を高速化する

  • 1017
    Like
  • 14
    Comment
More than 1 year has passed since last update.

tl;dr

よく使われるコマンドの一つに cd コマンドがあります。ターミナル生活の 80% 近くは cdls である、という英文記事を何処かで見かけました。それを効率化しようという Tips です。

目的

cd はよく使われるのに使い勝手が悪いコマンドである気がしてなりません。cd コマンドは有効なパス(相対パス、絶対パスは問わず)しか解釈してくれないからです。つまり、存在していて尚且つパスが解決できるものに限るのです。例えば、ホームディレクトリにいるときに、/home/lisa/work/dir に行こうとして cd dir とだけタイプしても no such file or directory (そんなディレクトリは見当たらないよ!)と言われてしまいます。きちんとした経路でなければならないのです。いちいちパスを覚えていない場合や、部分的にしか思い出せない場合には結構面倒ですよね。たかがディレクトリ移動です。

enhancd

そこでとあるプラグインをつくりました。既存の cd をオーバライドして強化したコマンドです。

b4b4r07/enhancd ❤ GitHub

:rocket: A next-generation cd command with an interactive filter :sparkles:

まずは、実際の動作を御覧ください。

特徴

  • ディレクトリ移動のたびに、移動先のパスをログに溜め込んでいます
  • 不明確なパスが与えられたときに限り、ログからベースネームを検索します
  • ログはきちんと履歴順にソート、一意処理がされているので遡るように閲覧できます
  • 検索結果が 1 件のみのとき、そのまま移動します
  • 検索結果が複数件あるときは、インタラクティブ・フィルタリングツールで絞り込みます
  • 使用するフィルタリングツールは複数指定でき、有効なものから使われます
  • ログの育成が高速に行われる仕組みがあります(後述)

基本的な動作はこれに終始しています。

それ以外に拡張的な機能が以下 3 つあります。

cd -

  • 既存の cd - を拡張していて、過去ログから最新 10 件に限って実行します
  • このとき、現在いるディレクトリは候補から外されるので、ひとつ前のディレクトリに戻りたいときは、すぐさまエンターを押せば戻ることができます

cd ..

  • cd .. は親ディレクトリ(..)に戻ることを意味しますが、これが複数続くと非常に面倒で、何回 .. を繰り返すか考えなければなりません
  • この長ったらしい cd ../../.. を解決するソリューション、zsh-bd プラグインを真似た機能を取り込みました

    • zsh-bd デモ

    • enhancd デモ

  • zsh-bd より優れている点が、親ディレクトリ名が重複する場合です。src/some/src といったように src が重複していると zsh-bd ではうまく扱えませんが、enhancd ではユニーク ID を振ることで、これを解決しています

Fuzzy search

  • これは最近実装した、enhancd の中でも特に強力な機能で、ディレクトリ名のあいまい検索を可能とします

    • enhancd Fuzzy-search デモ

    • texttesttxt を検索できました)

  • ディレクトリ名を打ち間違えたり、きちんと思い出せない場合に威力を発揮します

  • 後述しますが、このデモではインタラクティブ・フィルタリングツールとして fzf を使っています。これは、fzf があいまいなフィルタを可能としているので、enhancd の機能である、あいまい検索との親和性が見込めるためです

使い方

通常のビルドインと大きく変わりません。引数にはパス以外に、単にディレクトリ名だけを与えることができます。

$ cd [DIR]

もちろん、DIR を省略することができて、これも既存のものを拡張した機能になっています。通常 cd では、引数がすべて省略されると環境変数 $HOME に移動します。enhancd では、履歴の順序にかかわらず、$HOME がログのトップにきます。つまり cd エンターするだけで、ホームディレクトリに移動することが可能です。

オプションなどは今のところ(v2.1.3)ありません。唯一、- くらいでしょうか。

インタラクティブ・フィルタリングツールについて

Interactive grep などとも言われるツールのことです。enhancd では移動先の候補が複数ある場合、percol や、peco などによってインタラクティブにフィルタリングしています。enhancd はどれか一つを必要としているので、別途インストールする必要があります。

カスタマイズ

$ENHANCD_FILTER

環境変数によって先のインタラクティブ・フィルタリングツールを指定できます。デフォルトで fzf:peco:percol:gof といったように設定されているのでユーザは気にする必要はありませんが、インストール済みで尚且つ先頭にあるものが、実際のフィルタリングに使われるので、これの順番を入れ替えることで使いたいものを使用できます。

$ echo $ENHANCD_FILTER
fzf:peco:percol:gof

順番を入れ替え

$ ENHANCD_FILTER=no-installed:/usr/bin/peco:percol

パスによる指定もできる他、存在しないフィルタリングツールを指定していても無視されるので問題ありません。

$ENHANCD_DIR

enhancd がログファイルやそのバックアップファイルなどを保存しているディレクトリです。デフォルトでは ~/.enhancd になっています。

インストール

ただのシェルスクリプトなので、ファイルを保存して source するだけです。

enhancd は、bash、zsh、fish で動きます。zsh 使いは zplug を使うと fzf/peco などもすべてまとめてインストールすることが出来ます。

zplug "junegunn/fzf-bin", \
    as:command, \
    file:"fzf", \
    from:gh-r, \
    | zplug "b4b4r07/enhancd", of:enhancd.sh

でいいです。

ギミック

  • ログの育成が高速に行われる仕組み

    面白い機能として、「ログを高速で育成」する仕組みがあります。ログに溜め込まれるものは、「訪れた」ディレクトリですが、そのディレクトリまでの階層パスすべてと訪れたディレクトリにある子ディレクトリ(1階層分)をログの先頭に追記します。先頭なのは、履歴としての順番をおかしくしないためです。この追記システムにより、高速でログが膨らんで行きます。

  • cd の実態

    実際はエイリアスになっています。なので unalias cd すると通常の cd に戻ります。一時的に解除したい際はこれでどうぞ。

  • 安全装置

    enhancd ではパスが辿れないディレクトリ名を渡されたときにログから検索するシステムがありますが、ログをフィルタリングツールに流す前に事前に既に存在しないディレクトリを消したり、一意処理したりしています。通常、何らかの操作のために使用されているファイルをそのままリダイレクトなどで上書きすると消えてしまう性質があります(参考:一時ファイル無しで、ファイルを上書き更新するシェルスクリプト)。そのため中間ファイルを作成して、元ファイルを削除、その中間ファイルをリネームして元ファイルとする、といった処理を行っています。つまり、一時的にログを削除しています。このファイル操作は結構危険で、うっかり何らかのミスがあるとログが消えてしまうからです。そのために、慎重なランダム文字列を作成して(一時ファイルに使う)中間ファイルのバックアップを作成し、ミスによるログ消失時に復元するようにしています。また、処理が終わるとすべての関係のないファイルを消しています。
    そのため、これだけの I/O 処理が行われています。

    一回のcdに行われるI/O処理(ディレクトリを監視した)
    [Aug 10 10:25:48] Added: enhancd.log (7437 Bytes, 158ef2fb1446cdcc)
    [Aug 10 10:25:49] Added: enhancd.1008157996911412 (0 Bytes, e3b0c44298fc1c14)
    [Aug 10 10:25:49] Added: enhancd.backup (7437 Bytes, 158ef2fb1446cdcc)
    [Aug 10 10:25:49] Deleted: enhancd.log (7437 Bytes, 158ef2fb1446cdcc)
    [Aug 10 10:25:49] Added: enhancd.log (7233 Bytes, 95a21d1b9cdf7e45)
    [Aug 10 10:25:49] Deleted: enhancd.1008157996911412 (0 Bytes, e3b0c44298fc1c14)
    [Aug 10 10:25:49] Deleted: enhancd.backup (7437 Bytes, 158ef2fb1446cdcc)
    [Aug 10 10:25:49] Added: enhancd.1008157996923071 (105 Bytes, f8e01f07239f90a8)
    [Aug 10 10:25:49] Added: enhancd.backup (7233 Bytes, 95a21d1b9cdf7e45)
    [Aug 10 10:25:49] Deleted: enhancd.log (7233 Bytes, 95a21d1b9cdf7e45)
    [Aug 10 10:25:49] Added: enhancd.log (7233 Bytes, 95a21d1b9cdf7e45)
    [Aug 10 10:25:49] Deleted: enhancd.1008157996923071 (105 Bytes, f8e01f07239f90a8)
    [Aug 10 10:25:49] Deleted: enhancd.backup (7233 Bytes, 95a21d1b9cdf7e45)
    [Aug 10 10:26:02] Added: enhancd.1008157996914781 (0 Bytes, e3b0c44298fc1c14)
    [Aug 10 10:26:02] Added: enhancd.backup (7233 Bytes, 95a21d1b9cdf7e45)
    [Aug 10 10:26:02] Deleted: enhancd.log (7233 Bytes, 95a21d1b9cdf7e45)
    [Aug 10 10:26:02] Added: enhancd.log (7437 Bytes, 158ef2fb1446cdcc)
    [Aug 10 10:26:02] Deleted: enhancd.1008157996914781 (0 Bytes, e3b0c44298fc1c14)
    [Aug 10 10:26:03] Deleted: enhancd.backup (7233 Bytes, 95a21d1b9cdf7e45)
    

実装

enhancd の実装についてです。別記事にしたので気になれば参照してください。

最後に

とりわけ bash ユーザには重宝するプラグインです。zsh ユーザに関しても zsh の機能である auto_cd やその他移動系の設定がありますが、こっちのほうがより高速に・対話的に移動ができるでしょう。中でもあいまい検索によるディレクトリ補完は、更にターミナル生活を便利にしてくれます。

このプラグインはワンファイルで完結するためサッと落としてきて source すれば使えるという簡単さも強みです。試して気に入らなければ削除してください。

$ rm -r ~/.enhancd

参考