👏

ディレクトリの移動は cd コマンドよりも pushd コマンドのほうが便利!

2021/02/21に公開

コマンドラインで作業するときにおそらく一番目か二番目によく使うのが cd コマンド。たった 2 文字しかないので打つのも簡単です。しかし、深い高層のディレクトリ間を頻繁に移動するときに毎回ディレクトリを指定するのが面倒なことがあります。

下のディレクトリツリーを例に取ります。
ディレクトリツリー.png

カレントディレクトリが workspace1/html だったとします。ここから workspace2/html に移動したい場合は cd ../../workspace2/html と入力します。そして今度は workspace1/js に移動したくなったら cd ../../workspace1/js と入力します。workspace2/js に移動したくなったら cd ../../workspace2/js と入力……ちょっと面倒ですよね。

このツリー構造はそこまで深くないので workspace1 内のディレクトリから workspace2 のディレクトリに移動しようと思ったら ../../workspace... だけでいいですが、フレームワークを使っていたりするともっと階層が深くなり、../../../../workspace... のようになり、.. を打つだけでも大変です。

ディレクトリスタックを使おう!

ディレクトリスタックとは、ディレクトリの位置をフルパスで複数保存しておくためのスタック(記憶領域)です。ディレクトリスタックにディレクトリのパスを保存するには pushd、ディレクトリスタックの状態を確認するには dirs、ディレクトリスタックのパスを削除するには popd を使います。

実際に試してみましょう。先に紹介したツリー構造で、workspace1/html にいるとします。ここで、cd コマンドの代わりに pushd コマンドを使用して、workspace2/html に移動します。
$ pushd ../../workspace2/html
これで、workspace2/html に移動し、workspace1/html へのフルパスがスタックに積まれました。dirs で確認してみましょう。

$ dirs
0  ~/workspace2/html
1  ~/workspace1/html

ここでもう一度、pushd を実行すると、workspace2/html から workspace1/html に移動できます。さらに pushd を実行すると workspce2/html にまた戻ってくることができます。

どういう仕組みなのか?

pushd コマンドは、カレントディレクトリのフルパスをディレクトリスタックに積んで、指定した引数のディレクトリに移動するコマンドです。移動先のディレクトリを指定せずに単に pushd だけで実行した場合は直前にいたディレクトリに移動できます。

$ pwd
~/workspace1/html
$ dirs
0 ~/workspace1/html # カレントディレクトリが 0 番目に積まれている
$ pushd ../../workspace2/html
$ dirs
0 ~/workspace2/html # 0 番目はカレントディレクトリ
1 ~/workspace1/html # 移動前直前のディレクトリが積まれる
$ pushd ../../workspace1/js
$ dirs
0 ~/workspace1/js # 0 番目はカレントディレクトリ
1 ~/workspace2/html # 移動前直前のディレクトリが積まれる
2 ~/workspace1/html # 古くなるごとに下に下がる
$ pushd # 移動先を指定しないと
0 ~/workspace2/html # 直前にいたディレクトリに移動する
1 ~/workspace1/js # pushd 直前のディレクトリが積まれる
2 ~/workspace1/html

pushd で移動すると移動前のディレクトリをスタックに保存して移動するので、もう一度戻る際にはパスを指定せずに pushd を実行すれば戻ることができます。dirs でスタックを確認したときの 0 番目がカレントディレクトリ、1 番目に直前にいたディレクトリ、2 番目はさらにその前にいたディレクトリ、それ以降も同様に、古くなるごとに後ろに積まれていきます。

カレントディレクトリ(0 番目)から直前にいたディレクトリ(1 番目)に移動するには pushd 単体で良いのですが、2 つ前にいたディレクトリ(2 番目)に移動したい場合は pushd +2 とします。pushd +(番号) と入力することで dirs で確認した際の番号のディレクトリに飛ぶことができます。つまり、pushd 単体は pushd +1 と同じということですね!

要らなくなったパスは popd で削除!

ディレクトリスタックが以下の状態だったとします。

0 ~/workspace2/html
1 ~/workspace1/js
2 ~/workspace1/html

ここで、workspace2/html 内のコードはすべて書き終えたので、もうこのディレクトリに来ることはなくなったとします。このままだと workspace2/html のパスがスタックに積まれたままなので、移動するときの候補が多くなり、どこに移動すればいいのかがわかりにくくなってしまいます。

既に作業を終えて、来ることがなくなったディレクトリは popd で削除します。単に popd だけで実行するとカレントディレクトリ(0 番目)がスタックから削除されます。カレントディレクトリがスタックから削除されるので、popd を実行すると自動的に 1 番目のパス(workspace1/js)に移動することに注意してください。

$ popd
$ dirs
0 ~/workspace1/js # popd によって自動的に workspace1/js に移動することに注意!
1 ~/workspace1/html
0 ~/workspace2/html
1 ~/workspace1/js
2 ~/workspace1/html

popd 単体だと 0 番目の workspace2/html が削除されましたが、0 番目ではなく 1 番目を削除したい場合は popd +1、2 番目を削除したい場合は popd +2 で削除できます。

スタックに保存せずに移動したい場合

しかし時には、ディレクトリスタックに保存するほど頻繁にアクセスしないようなディレクトリに移動したい場合もあります。そのときは cd で移動します。ただし cd だと移動前のカレントディレクトリのパスを上書きしてしまうので、移動前のカレントディレクトリのパスを保持したまま、スタックに保存したくないディレクトリに移動したい場合は以下のようにします。

$ dirs
0 ~/workspace2/html
1 ~/workspace1/js
2 ~/workspace1/html
$ pushd .
0 ~/workspace2/html
1 ~/workspace2/html # 同じパスがコピーされる
2 ~/workspace1/js
3 ~/workspace1/html
$ cd temp # スタックに保存したくないディレクトリに移動
$ dirs
0 ~/workspace2/html/temp # ここから 1 番目に戻るときは popd すればスタックから削除される
1 ~/workspace2/html # ここは残った状態
2 ~/workspace1/js
3 ~/workspace1/html

cd で移動しても 0 番目はカレントディレクトリなので一時的には保存されてしまいますが、popd すればスタックから削除しつつ、前のディレクトリに戻ることができます。

エイリアスの設定

さて、ここまでの説明では、dirs を実行したときに、左に番号が表示され、各パスが 1 行ごと表示されていますが、これは実際にはオプションをつけて dirs -v としなければいけません。単に dirs と入力すると、各パスがすべて 1 行で表示されてしまう上に、番号が表示されないので、とても不便です。でも dirs -v と毎回入力するのも面倒くさい…そんなときはエイリアスの出番です。.bashrc(zsh の場合は .zshrc)に以下の一行を付け足します。.bashrc(.zshrc)はホームディレクトリの隠しファイルです。

.bashrc
alias dirs='dirs -v'

追加して保存したら .bashrc を再読込します。

$ source ~/.bashrc

これで、dirs と入力するだけで番号が表示されるようになりました!

まとめ

  • スタックを確認するには dirs
  • スタックにパスを保存するには pushd
  • スタックからパスを削除するには popd
  • pushd 単体では、1 番目のディレクトリに移動する
  • popd 単体では 0 番目(カレントディレクトリ)に移動する
  • 2 番目のディレクトリに移動したいときには pushd +2 (popd も同じ)
  • スタックに保存したくないときは cd で移動する
  • dirs はエイリアスを設定すると便利
GitHubで編集を提案

Discussion