cd
読み:スィーディー
外語:cd

 カレントディレクトリを変更する、MS-DOSUNIXのコマンド。
目次

概要
 MS-DOSはシェル内部コマンドで、CHDIR または省略形の CD が使用できる。
 UNIXでもシェル内部コマンドである。

特徴

MS-DOS
 MS-DOSのCDコマンド(またはCHDIRコマンド)は、CD <パス> のように使うことで、指定したパスをカレントディレクトリとする。
 ドライブレターを指定した場合は、当該のドライブのカレントディレクトリを変更する。
 パラメーター無しで実行した場合、またはドライブレターのみを指定した場合は、現在のカレントディレクトリを表示する。このカレントディレクトリ表示機能は、UNIXでは pwd コマンドに相当する。

UNIX
 UNIXのシェルでも、指定したパスをカレントディレクトリとする。
 また、パラメーターなしで cd のみで実行すると、"cd ~" と同義、つまりそのユーザーのホームディレクトリに移動する。
 なお、UNIXではカレントディレクトリはプロセスごとに管理されるため、他のプロセスつまり外部コマンドで現在のシェルのカレントディレクトリを変更できない。
 従って、mkdirrmdir などは外部コマンドだが、cd だけはシェル内部コマンドとして実装されている。

/usr/bin/cdって何ですか
 FreeBSDなどBSDや、あるいはBSDカーネルを使用または影響を受けているOS XSolarisなどでは、外部コマンドとして /usr/bin/cd が存在する。
 しかしこれは、内蔵コマンドのcdのような動作はしない。上述のように、/usr/bin/cd を実行しても呼び出したシェルとは別プロセスであるので、呼び出し元のシェルに影響を与えることはないからである。
 ではなぜ存在するのか? は、FAQであるらしい。
 これは、POSIXの仕様で、シェルの内蔵コマンドであっても特別な内蔵コマンドを除いて exec() などのシステムコールから呼び出せるようにする、と定められており、その例外規定に cd が含まれていなかったためとされている。
 BSDは、この間抜けなPOSIXに準拠するために、このような無意味なコマンドを用意していることになる。
 なお、FreeBSDなどの場合、その他のコマンドと共有のシェルスクリプトがハードリンクとなっている。
#!/bin/sh
# $FreeBSD: release/9.1.0/usr.bin/alias/generic.sh 151635 2005-10-24 22:32:19Z cperciva $
# This file is in the public domain.
builtin ${0##*/} ${1+"$@"}
 builtinは、特定の環境でエラーが出ないように含めたもので、実質的に機能するのは次の部分。
${0##*/} ${1+"$@"}
 最初の部分は「/usr/bin/cd」である ${0} から最後の / 以降を取り出す。つまり「cd」を得る処理である。
 後の部分は「"$@"」と同様の動作で、引数部分がセットされることになるが、引数がない場合に「"$@"」が「""」になってしまうことを避けるため、技巧が凝らされている。
 結果としてこれは、シェルを起動し、その中の内部コマンドであるcdを実行する。
 しかし他のプロセスで動作する以上は、いくら頑張ってみても元のプロセスに影響が及ぶことはない。

gdbを使えば外部からでも
 では外部コマンドは絶対無理なのかというとそうでもなく、gdbなどを使えば例外的に可能である。
 Linuxのbashで確認した限りでは、次のように動作した。
$ pwd
/home
$ gdb -p $$ -q -n <<<'call chdir("/tmp")' >/dev/null
 カレントディレクトリを確認する。
$ pwd
/home
 変化していないように見えるが、ls コマンドなどは /tmp 以下が表示できるので、カレントディレクトリが変化したことは間違いない。そこで、procfsから確認する。
$ file /proc/self/cwd
/proc/self/cwd: symbolic link to `/tmp'
 プロセスのカレントディレクトリは確かに変わっていた。
 シェル内蔵コマンドではなく、外部コマンドのpwdを使ってみる。
$ /bin/pwd
/tmp
 ここから、シェル内蔵コマンドのpwdは、プロセスのカレントディレクトリ情報を逐一確認して表示しているのではなく、シェル内蔵コマンドのcdで設定した内容をそのまま表示していることが分かる。
 外部から強引に変更されることを想定していないためと思われる。

再検索