腳本裡 cd 成功,終端機卻沒移動?看懂 Bash 的工作目錄 / Why cd in a Script Does Not Move Your Terminal

目錄怎麼又回去了? / Why did the directory revert?

假設你在 Linux 的 Bash 終端機裡執行一支腳本,裡面明明寫了切換目錄,腳本也沒有報錯,結束後卻還停在原處。這通常不是路徑失靈,而是你把「另一個 shell 的工作目錄」,當成了眼前這個 shell 的狀態。

Imagine running a script in a Bash terminal on Linux. The script changes directory without an error, yet your terminal remains where it started. Usually the path is not broken: you have mistaken another shell’s working directory for the state of your current shell.

工作目錄是程序用來解讀相對路徑的起點,不是整台電腦共用的一個游標。以 bash go.sh 執行腳本時,新的 Bash 會繼承起始目錄;它之後呼叫 cd,只改變自己的工作目錄,並不把變更回寫給啟動它的 shell。[1]

The working directory is a process’s starting point for resolving relative paths, not a computer-wide cursor. Running bash go.sh starts another Bash that inherits the initial directory. Its subsequent cd changes its own working directory, without writing that change back to the shell that launched it. [1]

腳本 shell 繼承起始目錄,cd 只改變自身,外層目錄保持不變 / The script shell inherits its starting directory; cd changes only its own directory, leaving the outer shell unchanged.
圖一|繼承不等於回寫:腳本結束,外層仍在原處。原創示意圖,非產品或實測截圖。 / Figure 1 | Inheritance is not write-back: the outer shell stays put after the script exits. Original diagram, not a product or test screenshot.

同一行指令,不一定在同一個 shell / Same command, different shell

這裡談的是 Linux 上一般 Bash 指令的執行方式,不是圖形檔案管理員的導覽,也不是所有語言的特殊共享狀態。腳本仍然可以修改有權限的檔案;工作目錄不回寫,不代表它對外界沒有任何影響。

This discussion covers ordinary Bash command execution on Linux, not navigation in a graphical file manager or every language’s special shared state. A script can still modify files it has permission to write: not writing its working directory back does not mean it has no external effects.

所以,直接在提示字元輸入 cd 能留下效果,是因為它是 Bash 的內建指令,作用在目前的 shell。反過來,把 cd 放進括號形成子 shell,即使仍是內建指令,變更也留在子環境裡。判斷重點不只是哪個指令,而是它在哪個執行環境運作。[1][2]

Typing cd directly at the prompt persists because it is a Bash builtin acting in the current shell. In contrast, placing cd inside parentheses creates a subshell: even the builtin’s change stays in that child environment. What matters is not only the command, but the execution environment in which it runs. [1][2]

先做一個不寫檔的小觀察:在 Bash 依序輸入下方三行。中間的括號只在子 shell 切到根目錄並列印位置;最後一行則再次觀察外層目錄。本文依官方手冊解說,未把這段範例宣稱為本次 Linux 真機實測;若原本就在根目錄,前後自然看不出差異。

For a small observation that writes no files, enter the three lines below in Bash. The parenthesized commands change to the root directory and print it only in a subshell; the last line observes the outer directory again. This explanation follows the official manual, not a claimed Linux hardware test in this run. If you already started at root, naturally there will be no visible difference.

pwd
( cd / && pwd )
pwd

需要留下變更時,再決定怎麼執行 / Decide what should persist

若目的就是讓目前終端機切換目錄,可以直接輸入 cd,或定義在目前 shell 執行的函式。另一個選擇是用 source ./go.sh 讀入可信任的腳本,讓命令在目前 shell 執行;這不是單純「取得腳本結果」,而是讓腳本直接參與你的工作環境。[2]

To change the current terminal’s directory, use cd directly or define a function that runs in the current shell. Alternatively, source ./go.sh reads a trusted script and executes its commands in the current shell. This does not merely retrieve a script’s result: it lets the script participate directly in your working environment. [2]

因此,不要為了讓目錄留下來,就隨手讀入陌生腳本;它也可能改變變數、選項,甚至結束目前 shell。若只是想在別處完成一段工作,保留子 shell 反而清楚:進去工作,離開後不打擾原本位置。下次看到目錄「回來了」,先問是哪個 shell 在移動,而不是急著重寫路徑。

Do not source an unfamiliar script just to make a directory change persist: it may also change variables and options, or even exit the current shell. If you only need to do some work elsewhere, a subshell is a clear choice: enter, do the work, and leave the original location undisturbed. Next time a directory seems to “revert,” ask which shell moved before rewriting the path.

資料來源 / Sources

查核日期 / Checked: 2026-10-31。依官方文件整理;範例未宣稱本次 Linux 實測。 / Based on official documentation; examples are not claimed as Linux tests performed in this run.

  1. GNU Bash Reference Manual — Command Execution Environment
  2. GNU Bash Reference Manual — Bourne Shell Builtins (cd, . / source)

留言

熱門文章