rcmdnk's blog
Last update

ターミナルでのディレクトリ移動コマンドは最も良く使うコマンドだと思いますが、 良く使うコマンドだけに出来るだけ楽出来るようにしたいものです。

このページでは、数回前に居た時のディレクトリに戻りたい、 という時や、 複数のウィンドウで作業している時に、 一方のウィンドウで作業しているディレクトリに他方のウィンドウからも移動したい、 という時に簡単に移動出来るようなコマンドを紹介します。

cd

まずはcd(Change Directory)の簡単なまとめ。

1
2
3
cd directory # Go to directory
cd           # = cd ~, Go to $HOME
cd -         # Go to previous directory

通常、directoryをした場合、カレントディレクトリから相対的に移動するか、 /で始まればそれによって指定された絶対パスに移動します。

-を使うと直前に居たディレクトリに帰る事が出来、良く使うと思いますが、 1回-を使った後は、戻る前に居たディレクトリが記憶されるので、 cd -を繰り返すと前に居たディレクトリとカレントディレクトリを行ったり来たり するだけです。

さらに前のディレクトリに行きたいときは下の様に予めpushd等で 移動しておく必要があります。

ここでCDPATHと言うシェル変数があって、良く使う親ディレクトリの場所を 指定しておくと、どのディレクトリからcdしても、CDPATH内にかかれた 親ディレクトリ内に指定のディレクトリがある場合、そのディレクトリに移動します。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cd /tmp
$ mkdir -p test1/test2
$ CDPATH=/tmp/test1/
$ cd test2
/tmp/test1/test2
$ cd /tmp
$ mkdir test2
$ cd test2
/tmp/test1/test2
$ cd /tmp
$ cd ./test2
$ pwd
/tmp/test2

CDPATH内で指定されているディレクトリが最優先されているので、 カレントディレクトリに同名のディレクトリがあったとしても CDPATH内に書かれたディレクトリ内にあるディレクトリが優先されます。 (なので明示的に./を使う必要があります。)

逆に混乱の元にもなるので、余程特殊なディレクトリ名だけがあるような 親ディレクトリでない場合は使わないほうが無難です。

CDPATHへはPATH等と同様に:で区切って 複数のディレクトリを指定することが出来ます。

pushd/popd

cdの代わりにpushdを使うと移動と同時に移動先のディレクトリを記憶します。 popdを使うと記憶されたディレクトリの新しい順に 戻っていくことが出来ます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ cd /tmp
$ mkdir -p test1/test2
$ pushd test1/
/tmp/test1 /tmp
$ pushd test2/
/tmp/test1/test2 /tmp/test1 /tmp
$ pushd ../
/tmp/test1 /tmp/test1/test2 /tmp/test1 /tmp
$ popd
/tmp/test1/test2 /tmp/test1 /tmp
$ popd
/tmp/test1 /tmp
$ popd
/tmp
$ popd
bash: popd: directory stack empty
/tmp $

pushd/popdではさらに数字を指定することによって n回前のディレクトリに戻る、といったことも出来ますがここでは省略します。

cdをpushdのwrapperにする

過去の移動歴を覚えてくれるのは便利ですが、毎回pushdを するのは大変な上、ディレクトリがいちいち表示されて嫌なので、 cdpushdへのwrapper functionにしています。

cd_wrapper.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function cd {
  if [ $# = 0 ];then
    command cd
  elif [ "$1" = "-" ];then
    local opwd=$OLDPWD
    pushd . >/dev/null
    command cd $opwd
  elif [ -f "$1" ];then
    pushd . >/dev/null
    command cd $(dirname "$@")
  else
    pushd . >/dev/null
    command cd "$@"
  fi
}
alias bd="popd >/dev/null"

素直にalias cd='pushd >/dev/null'でも殆ど変わらないですが、 1番最初のディレクトリを記憶したり、 ディレクトリの中のファイル名まで指定してしまった時にその親ディレクトリに 移動したりと(Tabで探してる時等にたまに行きすぎてしまった時とか)、 細かいところを調整しています。

追記: 2014/06/22

pushdの機能を何か勘違いしてましたが、 pushd現在のディレクトリを保存して指定のディレクトリに移動 を行うので、まさに上でやりたかったことをそのままやっています。 なので上のwrapperのファイル以外の変更は全く無意味。。。 GitHubの方に公開してるsd_cl の方でも余計なことやってましたが治しました。

追記ここまで

popdも保存されているディレクトリ名が表示されるので 上の様にbd(Back Directoryのつもり)にaliasして 何も表示せずにディレクトリを遡って行ける様にしています。

使う場合は.bashrcにでも加えて下さい。

異なるプロセス上でディレクトリ情報を共有する

複数のターミナルを開いて作業していたり、 screen等で複数ウィンドウを開いて作業をしていると、 一方のウィンドウの作業ディレクトリに、他方のウィンドウも 移動させたい時が良くあると思います。

違うターミナルを開いている時はpwdでカレントディレクトリ を表示させてマウスでコピペしたりするでしょうし、 screenなどではコピーモードを使って表示された ディレクトリをコピペするかと思いますが、 ちょっと面倒です。

そこで、次の様な関数などを使って簡単にディレクトリ情報を共有するようにしています。

sd_cl.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# Directory store file
export LASTDIRFILE=$HOME/.lastDir
# Number of store directories
export NLASTDIR=20

function sd { # Save dir {{{
  # Set values
  local ldf=${LASTDIRFILE:-$HOME/.lastDir}
  local nld="${NLASTDIR:-20}"

  # Get last directories
  touch $ldf
  local dirs=()
  while read d;do
    dirs=("${dirs[@]}" "$d")
  done < $ldf
  local ld=${dirs[0]}

  # Push current directory
  local curdir=`pwd -P`
  if [ "$ld" != "$curdir" ];then
    dirs=("$curdir" "${dirs[@]}")
  fi

  # Store directories
  local i=0
  rm -f $ldf
  while [ $i -lt ${#dirs[@]} ] && [ $i -lt $NLASTDIR ];do
    echo "${dirs[$i]}" >> $ldf
    i=$((i+1))
  done
} # }}}

function cl { # Change directory to the Last directory {{{
  local HELP="
  Usage: cl [-lch] [-n <number> ]
  If there are no arguments, you will move to the last saved dirctory by sd command
  Arguments:
     -l              Show saved directories
     -c              Show saved directories and choose a directory
     -n              Move to <number>-th last directory
     -h              Print this HELP and exit
"

  # Set values
  local ldf=${LASTDIRFILE:-$HOME/.lastDir}

  # Initialize variables
  local nth=0
  local list=0
  local choice=0

  # OPTIND must be reset in function
  local optind_tmp=$OPTIND
  OPTIND=1

  # Get option
  while getopts cln:h OPT;do
    case $OPT in
      "c" ) choice=1 ;;
      "l" ) list=1 ;;
      "n" ) nth="$OPTARG" ;;
      "h" ) echo "$HELP" 1>&2;OPTIND=$optind_tmp;return ;;
      * ) echo "$HELP" 1>&2;OPTIND=$optind_tmp;return ;;
    esac
  done
  shift $(($OPTIND - 1))
  OPTIND=$optind_tmp

  # Get last directories
  touch $ldf
  local dirs=()
  while read d;do
    dirs=("${dirs[@]}" "$d")
  done < $ldf
  local ld=${dirs[0]}

  # List up and choose directory
  if [ $choice -eq  1 ] || [ $list -eq 1 ];then
    # List up stored directories
    local listnum=${#dirs[@]}
    local i=$((listnum-1))
    while [ $i -ge 0 ];do
      printf "%4d %s %4d\n" $i "${dirs[$i]}" $i
      i=$((i-1))
    done

    # Choose from STDIN
    if [ $choice -eq 1 ];then
      echo -n "choose directory number: "
      read nth
    fi
  fi

  # Change directory
  if [ $list != 1 ];then
    cd "${dirs[$nth]}"
  fi
} # }}}

sdと言う関数でカレントディレクトリを記憶して clと言う関数で記憶されたディレクトリに移動します。

一方のウィンドウでsdしてもう一方のウィンドウでclすれば同じディレクトリに 行けるわけです。

また、clオプションとして

  • cl -l : 記憶したディレクトリの一覧の表示
  • cl -c : 記憶したディレクトリの一覧を表示し、選択した番号のディレクトリへ移動
  • cl -n N: N番目の記憶されたディレクトリへ移動

が出来ます。

設定変数は

  • LASTDIRFILE: 記憶するディレクトリの
  • NLASTDIR: 記憶するディレクトリの数

上記設定でpushdが常に行われる設定にしていますが、 このsdを使うことで、1つのウィンドウだけで作業している時でも、 特定のディレクトリだけを覚えておいて後で簡単に戻る、という使い方も出来ます。

これも使う場合は.bashrcにでも加えください。

追記: 2013/12/27

sd/clコマンドアップデート:

ターミナルでのディレクトリ移動を保存、取り出しする

追記ここまで

Sponsored Links
Sponsored Links

« GNU screenでクリップボードの履歴を使えるようにする Octopressでのタグの運用 »

}