Bash的「|」到底有什麼用,cd..|pwd為什麼還是當前路徑?
"|"不是把前面的output變成後面的input嗎,那既然cd..是去上一層路徑,為什麼cd..|pwd反而還是在當前的路徑呢
管道前後的東西是同時(讀作:前後腳)執行的,但這個地方的問題跟「執行順序」沒有關係。很容易發現,就算是cd .. | anything
pwd
得到的輸出仍然是執行之前的當前路徑。man bash 搜索 Pipelines 一節最後一句:Each command in a pipeline is executed as a separate process (i.e., in a subshell).
即:就算 cd .. 這樣的「內部命令」,都是 bash -c cd .. 這樣通過 subshell 執行的。所以執行管道的 shell 本身不受影響。
管道可以把前一個命令的輸出當成後一個命令的輸入, 這個就可以把linux下的各種命令按自己的需要組合起來, 想想是不是有點像函數的中的鏈式調用? 不過管道前後的兩個命令不是在同一個一個進程中執行, 而是分別在當前shell進程的fork出來的不同子進程中執行的, 而兩個子進程繼承的當前路徑都是父進程的當前路徑。
管道不是順序執行的
cd沒有output,pwd也不讀input
以下是關於「為什麼 cd .. | pwd 執行後依然在當前路徑」的回答。
首先一點,在 一個 shell 中執行的程序都一般會被啟動為以此 shell 為父進程的子進程。當把幾個命令用管道連起來時,它們會被並行執行,並且其標準輸入輸出(stdin/stdout)會被連起來。
譬如說,當我執行「ls | sort | head -n 10」的時候,進程樹是這個樣子的: ├─bash─┬─ls
│ ├─sort
│ └─head -n 10
~ $ which ls
/bin/ls
~ $ which cd
which: no cd in (/bin:/usr/bin:/usr/local/bin)
可見 cd 並非一個可執行的程序。
令一方面,我們可以測試 cd 的效果。這裡用到 shell 語法「(&~ $ cd /
/ $
切換成功,試試子進程的方法:
~ $ (cd /)
~ $
不太有效。注意 cd 是個 shell 指令而非可執行程序,所以一般 shell 會開一個子 shell 來執行之。
那麼當執行「cd .. | pwd」到底發生了甚麼?
首先兩個子進程會被 shell 創建出來,一個是子 shell,一個是 pwd 程序,剛 fork 出來的子進程的當前目錄和父進程一致。這時的進程樹如下: ├─bash (cwd: ~) ─┬─bash (cwd: ~)
│ └─pwd (cwd: ~)
├─bash (cwd: ~) ─┬─bash (cwd: /home)
│ └─pwd (cwd: ~)
子 shell 執行完 cd 就結束了。這並不會影響到父 shell 和 pwd 進城的當前目錄。pwd 的作用就是輸出自己的當前目錄,所以它把 /home/xxx 列印出來然後也結束掉了。這時 stdout 上只有 /home/xxx 的輸出而已。
題主的理解有些偏差,如 @唐生 所言,cd 的沒有輸入也沒有輸出,pwd 只會輸出且不會讀取任何輸入。所以把這兩個命令用管道連起來沒有實質的意義。推薦閱讀:
※在Bash中按Ctrl-S為什麼會失去響應?
※20.6 Shell 循環表達式 (從新手到菜鳥的Linux教程)
※如何評價 Windows 版「bash」(及其相關 *nix 子系統)?
※什麼是 .bashrc,為什麼要編輯 .bashrc? | Linux 中國
※linux刪除根目錄後發生了什麼?