Linux / コマンド / cd - ディレクトリ移動

cdは、Linuxシェルで現在の作業ディレクトリを変更するコマンドです。絶対パスと相対パスで移動でき、引数なしでホームディレクトリに移動したり、cd -で直前のディレクトリに戻ったりすることもできます。

cdは現在のシェルの状態を変更する必要があるため、外部実行ファイルではなくシェル組み込みコマンドです。本記事ではBashを基準に、パスの移動、シンボリックリンクの扱い、CDPATHとスクリプトでの安全な使用法について説明します。

cdコマンドとは?

cdはchange directoryの略で、シェルの現在の作業ディレクトリ(current working directory)を変更します。以降に指定する相対パスは、変更されたディレクトリを基準に解釈されます。

現在の位置はpwdで確認できます。

pwd
cd /var/log
pwd

type cdを実行すると、Bash組み込みコマンドであることが確認できます。別のプログラムとして実行すると、子プロセスのディレクトリだけが変更され、親シェルには影響を与えられないため、シェル自体が実装しています。

基本的な文法

cd [-L] [-@] [ディレクトリ]
cd -P [-e] [-@] [ディレクトリ]

一般的には、移動するディレクトリだけを指定します。

cd /etc
cd projects

移動に成功すると終了ステータス 0 を返し、パスが存在しない場合や権限が不足している場合は 0 以外の値を返します。成功の可否が重要なスクリプトでは、終了ステータスを確認する必要があります。

絶対パスと相対パスで移動する

以下の projects、Downloads、/srv 以下のパスやプログラムは例です。各例は個別に、自分が利用できる実在するディレクトリとスクリプトへ置き換えて試してください。移動後は pwd で結果を確認します。

絶対パスを使用する

ルートディレクトリ / から始まる絶対パスは、現在の位置に関係なく同じ対象を指します。

cd /var/log
cd /usr/local/bin
cd /

運用手順やスクリプトで基準位置が明確である必要がある場合、絶対パスは理解しやすいです。

相対パスを使用する

相対パスは、現在の作業ディレクトリを基準に解釈されます。

cd documents
cd projects/web
cd ../backup

同じコマンドでも、実行する現在の位置によって異なるディレクトリに移動したり、失敗したりする可能性があります。移動前後の位置が重要な場合は pwd で確認してください。

ホーム、上位および以前のディレクトリに移動する

ホームディレクトリに移動する

引数なしでcdを実行すると、HOME変数で指定されたユーザーのホームディレクトリに移動します。チルダ展開を使用したcd ~も通常同じ結果です。

cd
cd ~
cd ~/Downloads

他のユーザーのホームディレクトリは、システムのアカウント情報に応じて~ユーザー名から参照できます。

cd ~alice

該当するユーザーが存在しない場合や、ホームパスにアクセスする権限がない場合は、移動できません。

現在および上位ディレクトリを表す

1つのドット . は現在のディレクトリ、2つのドット .. は上位ディレクトリを意味します。

cd .
cd ..
cd ../..
cd ../../shared

cd .は通常、位置を変更しません。複数段階上に移動する場合は、各段階ごとに../を使用します。...のように3つのドットを上位2段階として解釈する機能は標準的なBashの動作ではありません。

直前のディレクトリに戻る cd -

cd -はOLDPWDに保存された直前の作業ディレクトリに移動し、成功すると新しいパスを出力します。

cd /etc
cd /var/log
cd -

2つのディレクトリを交互に確認する際に便利です。現在のシェルで前のディレクトリ情報がまだ作成されていない場合、OLDPWD not setのエラーが発生することがあります。

スペースや特殊文字を含むパス

パスを引用符で囲む

スペースを含むパスは、1つの引数として渡されるように引用符で囲みます。

cd "Project Files"
cd '/srv/shared data'

変数をパスとして使用する場合も、値が複数の単語に分かれたり、グロブで展開されたりしないように、ダブルクォーテーションで囲むのが安全です。

target='/srv/shared data'
cd -- "$target"

バックスラッシュやオプションに見える名前

スペースの前にバックスラッシュを付けてエスケープすることもできます。

cd Project\ Files

名前がハイフンで始まる場合、オプションと誤解されないように ./ を付けるか、オプション終了表示 -- を使用します。

cd ./-archive
cd -- -archive

タブ自動補完を使用すると、シェルがパスの空白や特殊文字を適切にエスケープしてくれるため、入力ミスを減らすことができます。

PWD と OLDPWD の理解

現在の位置を示す PWD

Bash は移動に成功すると PWD 変数に新しい作業ディレクトリを保存します。pwd コマンドと比較して、現在のシェルが記憶している論理パスを確認できます。

printf '%s\n' "$PWD"
pwd

~+ も Bash のチルダ展開で PWD の値に置き換えられます。

printf '%s\n' ~+

以前の位置を示す OLDPWD

移動が成功すると、既存の作業ディレクトリが OLDPWD に保存されます。cd - はこの値を使用します。

printf '%s\n' "$OLDPWD"
printf '%s\n' ~-

シェル起動直後やまだディレクトリを移動していない状況では、OLDPWDが存在しない場合があります。

シンボリックリンクと-L、-Pオプション

シンボリックリンクを含むパスでは、シェルが記憶する論理パスとファイルシステムで解釈された物理パスが異なることがあります。

論理パスを維持する-L

-Lはデフォルト動作で、パスの..を論理的なパス構成要素に基づいて処理します。シンボリックリンク名を通じて移動した場合、その名前がPWDにも保持される可能性があります。

cd -L /srv/current
pwd

ユーザーが入力したパス構造を維持するため、プロジェクトリンクや現在のリリースリンクに沿って作業する際に理解しやすくなります。

物理パスに従う-P

-Pは移動過程でシンボリックリンクを物理的な対象パスとして解釈します。実際のファイルシステム上の位置を確認したり、リンク対象に基づいて..を処理する必要がある場合に使用します。

cd -P /srv/current
pwd -P

-eは、-Pと一緒に使用した場合に、移動後の現在の物理パスを確定できないと失敗状態を返します。

cd -P -e /srv/current

CDPATHでよく行く場所を検索する

CDPATHは、cdがスラッシュで始まらないディレクトリ名を探すときに使用する検索パスです。実行ファイルを探すPATHに似ていますが、ディレクトリ移動にのみ適用されます。

CDPATH設定例

CDPATH=.:~/projects:/srv/apps
export CDPATH
cd sample-app

コロンで区切られた各場所でsample-appを探します。空の項目または.は現在のディレクトリを意味します。現在の場所の同じ名前を優先したい場合は、.を先頭に置く方法が理解しやすいです。

CDPATH使用時の注意点

cdが空でないCDPATH項目でディレクトリを探すと、移動した絶対パスを標準出力に表示できます。対話型シェルでは便利ですが、スクリプトの出力に予期しないパスが混ざる可能性があります。

自動化では絶対パスまたは明確な相対パスを使用し、必要であればCDPATH=でそのコマンドの検索パスの影響を取り除いてください。

CDPATH= cd -- ./build

移動が成功したときだけ次のコマンドを実行する

cdが失敗した状態で次のコマンドを実行し続けると、意図しないディレクトリでファイルを作成または削除する可能性があります。&& でつなぐと、移動に成功した場合だけ次の処理を実行できます。

cd /srv/app && ./deploy.sh

複数行のスクリプトでは、失敗時に明示的に終了するかエラーを処理します。

cd /srv/app || {
  printf '%s\n' '作業ディレクトリに移動できません.' >&2
  exit 1
}

./deploy.sh

cd パス; コマンドのようにセミコロンだけ使用すると、移動が失敗しても次のコマンドが実行されます。

スクリプトとサブシェルでのcdの使用

スクリプトが親シェルの場所を変更できない理由

再現するには専用の空の作業ディレクトリで mkdir -- cd-practice-target を実行します。change-directory.sh というファイルを作り、最初の行に #!/usr/bin/env bash、次の行に cd -- ./cd-practice-target && pwd と書いて保存します。内容はこの2行だけです。chmod u+x change-directory.sh で実行可能にして、以下を実行してください。スクリプト内の pwd は子ディレクトリを表示しますが、終了後の pwd は元の作業ディレクトリを表示します。後述の source の例を同じ場所から実行すると、現在のシェルも子ディレクトリへ移動します。

通常実行されるシェルスクリプトは別のプロセスで動作するため、スクリプト内のcdはそのプロセスと子にのみ影響を与えます。スクリプトが終了した後、呼び出したターミナルの作業ディレクトリはそのままです。

./change-directory.sh
pwd

現在のシェルの位置を変更するには関数を定義するかスクリプトをsourceで実行できますが、source で読み込んだスクリプトは現在のシェルの変数やオプションまで変更できるため、信頼できる内容か確認する必要があります。

source ./change-directory.sh

作業後に元の位置を維持するサブシェル

特定のディレクトリでのみ作業し、呼び出したシェルの位置を維持したい場合は、括弧でサブシェルを作ることができます。

(
  cd /srv/app && ./build.sh
)

括弧内でのディレクトリ変更はサブシェルが終了すると消えます。現在のシェルで移動して戻る場合、既存のパスを直接保存する代わりにpushdとpopdも使用できます。

sudo cdが動作しない理由

sudo cd /rootは通常使用できません。cdは現在のシェルの組み込みコマンドであり、sudoが開始した別のプロセスは親シェルの作業ディレクトリを変更できないためです。

管理者シェル自体が必要な場合は、権限ポリシーに従って次のような方法で新しいログインシェルを開始できます。

sudo -i

1つのコマンドだけを特定のディレクトリで管理者権限で実行したい場合、現在のシェルから移動した後、そのコマンドにのみsudoを適用するか、別のシェルに作業パスとコマンドを明示します。

cd /srv/app && sudo ./maintenance.sh
sudo sh -c 'cd /srv/app && ./maintenance.sh'

管理者権限は必要な範囲でのみ使用し、パスや実行ファイルが信頼できるか確認してください。

cd、pushd と popd の比較

コマンド 主な用途 特徴
cd 指定したディレクトリに移動します。 OLDPWD を使って直前の位置に戻ることができます。
pushd 現在の位置をディレクトリスタックに保存しながら移動します。 複数の場所を行き来する際に便利で、Bashがスタックを管理します。
popd 既定ではスタックの先頭を取り除き、新しい先頭のディレクトリへ移動します。 pushd と組み合わせて保存した位置を復元します。
dirs 現在のディレクトリスタックを確認します。 移動せずにスタックの状態だけを表示することができます。

よく使う移動コマンド

コマンド 説明
cd 現在のユーザーのホームディレクトリに移動します。
cd ~ チルダ展開を利用してホームディレクトリに移動します。
cd .. 上位ディレクトリに移動します。
cd ../.. 2段階上のディレクトリに移動します。
cd - 直前の作業ディレクトリに戻ります。
cd / ファイルシステムのルートディレクトリに移動します。
cd ~/projects ホーム下のprojectsディレクトリに移動します。
cd -P パス シンボリックリンクを解釈した物理パスに従って移動します。

オプションまとめ

オプション 説明
-L 論理パスを使用します。Bashのデフォルトの動作であり、シンボリックリンク名をパスに保持できます。
-P シンボリックリンクを物理的なターゲットパスとして解釈して移動します。
-e -Pと共に使用し、移動後物理的なカレントパスを確定できない場合は失敗ステータスを返します。
-@ 対応するシステムでファイルの拡張属性をディレクトリのように表示します。一般的なLinux環境ではサポートされない場合があります。
-- オプションの終了を示し、ハイフンで始まるディレクトリ名を引数として扱う際に使用します。

よく発生するエラー

No such file or directory

パスが存在しないか、現在の位置を誤って想定している可能性があります。pwdで基準位置を確認し、パスの大文字小文字や空白をチェックしてください。

pwd
ls -ld -- "対象パス"

Permission denied

対象ディレクトリやパスの中間ディレクトリに探索権限がない可能性があります。ディレクトリに移動するには、パスを構成する各ディレクトリに実行権限が必要です。

namei -l /path/to/directory

権限を任意に広げる前に、そのパスにアクセスする必要があるユーザーかどうか、適切なグループまたはアクセス制御リスト(ACL)の設定を確認してください。

Not a directory

パスの最後の項目や中間構成要素が通常のファイルである可能性があります。fileとls -ldで種類を確認してください。

file -- "対象パス"
ls -ld -- "対象パス"

FAQ

cdコマンドを実行したのに何も出力されないのは正常ですか?

正常です。一般的なパスへの移動に成功したcdは出力されません。現在の位置はpwdで確認でき、cd -やCDPATHで見つけたパスは成功時に新しいパスを出力できます。

親ディレクトリに二段階で移動するにはどうすればよいですか?

cd ../..を使用します。各..は上位ディレクトリの1段階を意味し、スラッシュでつなぎます。

スクリプトで現在のターミナルディレクトリを変更できますか?

通常実行されるスクリプトでは親シェルのディレクトリを変更できません。現在のシェルに影響を与えるには、シェル関数やsourceが必要ですが、現在のシェルの他の状態も変更する可能性があるため、信頼できるコードでのみ使用してください。

参考資料