LoginSignup
50
58

More than 5 years have passed since last update.

cdによるディレクトリ移動を効率化

Posted at

はじめに

私はいつもbashを使っています。
cdでディレクトリに移動を行なっていますが、この移動がいつも非効率だなと思っていました。
cd -で直前のディレクトリには戻れますが、それ以前に移動したディレクトリに再び移動したい場合は相対パスでもう一度入力し直さなければいけないのでだるいです。
一時期pushdpopdを利用していた時がありましたが、慣れなかったので今はcdによる移動のみです。
今回はこのcdによる移動を効率化したいと思います。

pushd・popd・dirs

今回の効率化を実装するにおいて重要なコマンドが3つあります。
1. pushd
2. popd
3. dirs
上記のコマンドを使って.bashrcを編集したいと思います。
念のためちょっとこのコマンドの紹介をしたいと思います。

pushd
cdコマンドと同じく引数で指定したディレクトリに移動することが出来るコマンドです。この時、移動前のカレントディレクトリをスタックに保存して指定されたディレクトリに移動するというのがpushdの特徴です。

popd
pushdコマンドによってスタックに保存された最新ディレクトリに移動するのがpopdコマンドです。スタックという構造なので後入先出法になります。

dirs
pushdコマンドによって保存されているスタック情報を確認出来るのがdirsコマンドです。スタックのクリアなどもこのコマンドで実行することが出来ます。

ではこれらのコマンドを使ってcdコマンドの効率化をしていきましょう。

cdの情報をスタックに保存(cdコマンドの再定義)

本来のcdコマンドでは、移動前のカレントディレクトリ情報を保存する機能はありません。そこでcdコマンドをpushdコマンドで再定義します。
上記に以前pushdpopdを利用していたと書きましたが、5文字も打ってられない!めんどくさい!という理由からやめてしまいました。今思えばエイリアスしとけばそっちで慣れたかもしれないです。再定義しておけば同じ機能をいつものcdコマンドで実現出来ます。
更に今回は移動履歴に重複がある場合余計にスタックに保存しないようになっています。
コードは以下のとおり。

.bashrc
# 履歴を記録するcdの再定義(pushdの利用)
function cd {
    if [ -z "$1" ] ; then
        # cd 連打で余計な $DIRSTACK を増やさない
        test "$PWD" != "$HOME" && pushd $HOME > /dev/null
    else
        pushd "$1" > /dev/null
    fi  
}

cdの履歴を遡ったディレクトリ移動

cdコマンドを再定義したのでcdの移動履歴がスタックに保存されるようになります。次はこの履歴を一覧表示し遡りたいディレクトリを番号で指定するとそのディレクトリに移動出来るようにします。
コードは以下のとおり。

.bashrc
# cdの履歴の中から移動したいディレクトリを選択するcd historyの定義
function cdh {
    local dirnum
    dirs -v | sort -k 2 | uniq -f 1 | sort -n -k 1 | head -n $(( LINES - 3 ))
    read -p "select number: " dirnum
    if [ -z "$dirnum" ] ; then
        echo "$FUNCNAME: Abort." 1>&2
    elif ( echo $dirnum | egrep '^[[:digit:]]+$' > /dev/null ) ; then
        cd "$( echo ${DIRSTACK[$dirnum]} | sed -e "s;^~;$HOME;" )"
    else
        echo "$FUNCNAME: Wrong." 1>&2
    fi
}

cdの履歴を遡るディレクトリ移動

cd historyで過去のディレクトリを指定して移動出来るようになりましたが、ただ単に遡りたい時用にpopdコマンドを利用して実現できるcd backを紹介します。
コードは以下のとおり。

.bashrc
#cd履歴を辿るcd backの定義(popdの利用)
function cdb {
    local num=$1 i
    if [ -z "$num" -o "$num" = 1 ] ; then
        popd >/dev/null
        return
    elif [[ "$num" =~ ^[0-9]+$ ]] ; then
        for (( i=0 ; i<num ; i++ )) ; do
            popd >/dev/null
        done
        return
    else
        echo "cdback: argument is invalid." >&2
    fi
}

入力がめんどうなディレクトリへの簡易移動

ディレクトリ名に日本語を使っているとcdで移動するとき厄介ですよね。いつもむしゃくしゃしてます。また、入力しずらい面倒なディレクトリ名だった場合もありますよね。そんなとき、カレントディレクトリの一覧を表示して番号指定で移動出来るようにcd listを定義しました。
コードは以下のとおり。

.bashrc
# カレントディレクトリの中にあるディレクトリを番号指定で移動するcd listの定義
function cdl {
    local -a dirlist opt_f=false
    local i d num=0 dirnum opt opt_f
    while getopts ":f" opt ; do
        case $opt in
            f ) opt_f=true ;;
        esac
    done
    shift $(( OPTIND -1 ))
    dirlist[0]=..
    for d in * ; do test -d "$d" && dirlist[$((++num))]="$d" ; done
    for i in $( seq 0 $num ) ; do printf "%3d %s%b\n" $i "$( $opt_f && echo -n "$PWD/" )${dirlist[$i]}" ; done
    read -p "select number: " dirnum
    if [ -z "$dirnum" ] ; then
        echo "$FUNCNAME: Abort." 1>&2
    elif ( echo $dirnum | egrep '^[[:digit:]]+$' > /dev/null ) ; then
        cd "${dirlist[$dirnum]}"
    else
        echo "$FUNCNAME: Something wrong." 1>&2
    fi
}

おわりに

これでかなりディレクトリ移動が早くなると思います。
皆さんにも是非やってみてください。参考までにどうぞ。
今回は以下のサイトを参考にさせて頂きました。ありがとうございます。
こちらのサイトのほうが細かいソースの内容を説明しているので、確認したい人はこちらの記事も是非確認してみてください。

いかに素早く目的のディレクトリにcdするか、そのためのTips
http://qiita.com/xtetsuji/items/31bc53e92d94b1602b5d

50
58
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
58