bashでディレクトリ間の移動を便利にする、拡張cdコマンドを紹介します。
これを使うと、わざわざpushd
コマンドを使わずとも、自動的にディレクトリの履歴を保存してくれるようになります。
設定方法
最近の Cygwin/MSYS2 の .bashrc
スケルトンファイル (/etc/skel/.bashrc
) には、サンプルとして、この拡張cdコマンドが記載されています。
コメントには以下のように書かれています。
# Some example functions:
...
# b) function cd_func
# This function defines a 'cd' replacement function capable of keeping,
# displaying and accessing history of visited directories, up to 10 entries.
# To use it, uncomment it, source this file and try 'cd --'.
# acd_func 1.0.5, 10-nov-2004
# Petar Marinov, http:/geocities.com/h2428, this is public domain
これによると、パブリックドメインで公開されていたコードのようですが、geocitiesの閉鎖に伴い、元のサイトは見られなくなってしまっています。
cd_func
関数の本体は以下の通りです。これを .bashrc
にコピー&ペーストすれば設定完了です。
cd_func ()
{
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
[[ $? -ne 0 ]] && return 1
the_new_dir=$(pwd)
#
# 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=cd_func
使い方
cd
コマンドでディレクトリを移動すると、自動的に最新10個までのディレクトリの履歴が保存されます。
cd --
で、保存されている履歴が表示されます。
例:
$ cd --
0 ~
1 /etc
2 /usr/bin
cd -n
で、履歴の n 番目のディレクトリに移動することが出来ます。
この例の場合、cd -2
で/usr/bin
に移動します。
直前のディレクトリに戻るには、cd -1
だけでなく、従来通り cd -
も使えます。
autocdの挙動を模倣
bashには autocd
というオプションがあります。これを有効にすると、cd
を指定せずにディレクトリ名を指定するだけでディレクトリを移動できるようになります。
user@host:~$ shopt -s autocd
user@host:~$ /etc
cd -- "/etc"
user@host:/etc$
しかし、このautocdオプションには上記のcd_funcが適用されず、cd
無しで移動したディレクトリは履歴に反映されません。
そこで以下の設定を .bashrc
に追加することで、autocdオプションを使ったときと同様に cd
を省略しつつ、cd_funcの履歴に登録することができるようになります。(autocdオプションは shopt -u autocd
で無効化しておく必要があります。)
# Change PWD even without `cd`
function _err_handler {
if [ $? -eq 126 ] && [ -d "$BASH_COMMAND" ]; then
echo "cd_func \"$BASH_COMMAND\""
cd_func "$BASH_COMMAND"
fi
}
trap "_err_handler" ERR
例:
user@host:~$ /etc
-bash: /etc: Is a directory
cd_func "/etc"
user@host:/etc$ cd --
0 /etc
1 ~
(-bash: /etc: Is a directory
というエラーが表示されてしまう問題がありますが、目をつむりましょう。)