ディレクトリ移動を便利にするコマンド zoxide の使い方
ディレクトリ移動を便利にするコマンド zoxide の使い方 (環境は Ubuntu
でシェルは bash
です )
zsh
シェルだとディレクトリの移動に cd
を省略してパスだけで移動できたりする。fish
シェルでは cd
と入力すると移動頻度に応じて補完されたり fisher install jethrokuan/z
と zoxide
とは別の z コマンドがあったりする。zsh/fish
は補完が強力だったり他にも便利なとこがいっぱいあるんだろうけど bash
でももっと便利にディレクトリ移動したい。
目次
概要
zoxide は移動したディレクトリのパスをデータベース(~/.local/share/zoxide
)に保存して、移動頻度に応じてスコアを付ける。そのスコアが高いディレクトリは z
コマンドで短いキーワードで移動できたり zi
コマンドで上位表示される。
インストール
fzf コマンドが必要なのでインストールする
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf ~/.fzf/install
OR
sudo apt install fzf
zoxide
のインストール (installation に載ってますが一応)
curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash
OR
sudo apt install zoxide
~/.bashrc
追記。
eval "$(zoxide init bash)"
--cmd
オプションを使えばコマンド名を z
/ zi
から変更できるっぽい
使い方
cd
コマンドと同様に z
でディレクトリを移動するとデータベースに追加されてスコアが付けられる。
$ z ~/foo/bar/baz
z
コマンドで移動すると次回から最後のディレクトリ名(検索対象が最後のディレクトリ名なので)で移動できるようになる
$ z baz $ pwd /home/user/foo/bar/baz
登録されてるディレクトリは短いキーワードで移動できる(データベースの登録件数が増えてくるとスコアによってどこに行けるか変わる)
$ z ~/Downloads $ z ~/ $ pwd /home/user $ z d $ pwd /home/user/Downloads
短いキーワードでどこに移動できるか確認
$ for v in $(echo {a..z}); do printf "%s: " "$v"; zoxide query "$v"; done a: /home/user/Downloads b: /home/user/Dropbox c: /home/user/.local d: /home/user/Downloads e: /etc f: /home/user/.config . . .
zi
コマンドは fzf
を使ってベータベースに登録されてるディレクトリを検索して移動できる
$ zi
zoxideコマンド
z
と zi
はどちらも関数なので以下本体である zoxide
コマンドの使い方。zoxide
のヘルプはシンプルで分かりやすぎるのでヘルプ見る方がいいかもしれない。
type z
で関数の内容が見れる
$ type z z is a function z () { if [ "$#" -eq 0 ]; then _z_cd ~; else if [ "$#" -eq 1 ] && [ "$1" = '-' ]; then if [ -n "$OLDPWD" ]; then _z_cd "$OLDPWD"; else echo 'zoxide: $OLDPWD is not set'; return 1; fi; else _zoxide_result="$(zoxide query -- "$@")" && _z_cd "$_zoxide_result"; fi; fi }
パスの追加とスコアのインクリメント(.
で現在のディレクトリを追加)
$ zoxide add <path>
パスの削除(.
で現在のディレクトリを削除)
存在しないディレクトリは自動で削除されるのでディレクトリを rm -rf
しても zoxide remove
の必要はない
$ zoxide remove <path>
パス一覧
$ zoxide query -l
スコア付きのパス一覧
$ zoxide query -ls
検索(最後のディレクトリ名で検索しているっぽい)
$ zoxide query conf /home/user/.config
fzf
を使った検索
$ zoxide query -i
個人的な設定
z
と zi
は使わないので ~/.bashrc
から eval "$(zoxide init bash)"
を削除。
cd
コマンドに z
コマンドの機能を付けたいので alias
で cd
コマンドを関数に置き換える。zoxide
以外の部分は この記事にある cd
コマンドを拡張するやつです。以下の関数を .bash_functions
とかに書いて ~/.bashrc
に読み込む。source ~/.bashrc
でリロードすると反映される。--cmd
で cd
に置き換え可能だと書いてるけど試してない。
func_enhanced_cd() { local x2 the_new_dir adir index local -i cnt if [[ $1 == "--" ]]; then dirs -v return 0 fi the_new_dir=$1 [[ -z $1 ]] && the_new_dir=$HOME if [[ ${the_new_dir:0:1} == '-' ]]; then # # Extract dir N from dirs index=${the_new_dir:1} [[ -z $index ]] && index=1 adir=$(dirs +$index) [[ -z $adir ]] && return 1 the_new_dir=$adir fi # # '~' has to be substituted by ${HOME} [[ ${the_new_dir:0:1} == '~' ]] && the_new_dir="${HOME}${the_new_dir:1}" # # Now change to the new dir and add to the top of the stack pushd "${the_new_dir}" >/dev/null 2>&1 if [[ $? -ne 0 ]]; then local q v q="$(IFS=' '; echo "$*")" v="$(zoxide query $q 2>/dev/null)" # なんかダサいこと書いてるけどエラー表示させるために # zoxide query の検索がヒットしなければ # $the_new_dir を入れて再び pushd でエラーにする [ -z "$v" ] && v="${the_new_dir}" pushd "$v" >/dev/null [[ $? -ne 0 ]] && return 1 fi the_new_dir="$(pwd)" # ホームディレクトリとルートディレクトリは除外して # zoxide add でディレクトリの登録とスコアをインクリメントする local -a EXCLUDES=("$HOME" '/') local ok=true local v for v in "${EXCLUDES[@]}"; do [ "$the_new_dir" == "$v" ] && ok=false done "${ok}" && zoxide add "${the_new_dir}" >/dev/null 2>&1 # # Trim down everything beyond 11th entry popd -n +11 2>/dev/null 1>/dev/null # # Remove any other occurence of this dir, skipping the top of the stack for ((cnt = 1; cnt <= 10; cnt++)); do x2=$(dirs +${cnt} 2>/dev/null) [[ $? -ne 0 ]] && return 0 [[ ${x2:0:1} == '~' ]] && x2="${HOME}${x2:1}" if [[ "${x2}" == "${the_new_dir}" ]]; then popd -n +$cnt 2>/dev/null 1>/dev/null cnt=cnt-1 fi done return 0 } alias cd=func_enhanced_cd
使ってる関数に zi
を組み込む。以下の関数を .bash_functions
とかに書いて ~/.bashrc
に読み込む。source ~/.bashrc
でリロードすると反映される。
ff() { local -a MAXDEPTH=(-maxdepth 6) local -a HIDDEN=(-and ! -path '*\/\.*') local -a ARGS=() local FIND=false while (($# > 0)); do case "$1" in -*) [[ "$1" =~ ^-(.*[^afl0-9]+.*|)$ ]] && echo "Error: invalid option -- ‘$1‘" && return 1 [[ "$1" =~ ^-[^0-9]*([0-9]|[1-9][0-9]+) ]] && MAXDEPTH=(-maxdepth "${BASH_REMATCH[1]}") [[ "$1" =~ ^-[^-]*a ]] && HIDDEN=() [[ "$1" =~ ^-[^-]*f ]] && FIND=true [[ "$1" =~ ^-[^-]*l ]] && MAXDEPTH=() shift continue ;; esac ARGS+=("$1") shift done local v if "${FIND}"; then v=$(find "${ARGS[0]:-.}" "${MAXDEPTH[@]}" -type d "${HIDDEN[@]}" -and ! -regex '^\.$' -and ! -regex '.*/node_modules/.*' -print 2>/dev/null | sed -e "s/^${HOME//\//\\/}/\~/" | fzf --select-1 --no-multi) else # zoxide のパス一覧を fzf で検索する v=$(zoxide query -l | sed -e "s/^${HOME//\//\\/}/\~/" | fzf --query="$(IFS=' '; echo "${ARGS[*]}")" --select-1 --no-multi) fi [ -n "$v" ] && v="${v/~\//$HOME/}" [ -d "$v" ] && cd "$v" || return 0 }
この関数は ff
すると zi
コマンドのように fzf
で検索して cd
できる。ff -f
すると find
コマンドで現在のディレクトリ以下を探索した結果を fzf
で絞り込んで cd
できる。
一応 ff -f
のその他のオプションを説明すると -fa
で .
から始まる非表示なディレクトリを検索対象に含める。 -f10
とか -数字
で階層制限を指定できる(デフォルトは local -a MAXDEPTH=(-maxdepth 6)
の部分で 6)。-fl
で階層制限なし。ホームディレクトリからすべてのディレクトリを検索する場合は ff -fal ~