林博仁 Buo-ren Lin says to Ubuntu 台灣社群
在 Bash 等 POSIX shell 裡,`2>&1` 是什麼意思? (★ 105 分) 在 Bash 等 POSIX shell(POSIX:可攜式作業系統介面標準)裡,`2>&1` 用來把標準錯誤輸出 stderr(檔案描述子 file descriptor 2)導向到「當下」標準輸出 stdout(檔案描述子 1)所指向的位置,讓兩種輸出合併成同一條串流,方便再拿去管線處理(例如 `| head`、`| grep`)或統一寫入檔案。這裡的關鍵在 `&`:它告訴 shell 右側的 `1` 代表「檔案描述子 1」,不是名為 `1` 的檔案;因此 `2>1` 其實會被解讀成「把 stderr 重新導向到檔名為 1 的檔案」。 文章也整理了常見重導向寫法:`>` 代表覆寫輸出到檔案、`>>` 代表附加,且可明確指定來源描述子,例如 `1>file` 是 stdout、`2>file` 是 stderr。`2>&1` 的本質是把描述子做「複製/對應」(常以 Unix 系統呼叫 system call 的 `dup2(1, 2)` 來理解),因此「順序」非常重要:shell 會由左到右套用重導向,所以 `cmd >file 2>&1` 會讓 stdout 先去 `file`,接著 stderr 再跟到同一個目的地;但 `cmd 2>&1 >file` 會先把 stderr 指向當時的 stdout(通常是終端機),之後才把 stdout 改到 `file`,造成兩者沒有真的寫到同一處。文中也提到一些捷徑語法,例如把 stdout+stderr 一起導到檔案的 `&>file`(或 `>&file`),以及把 stdout+stderr 一起送進管線的 `|&`(常見於 Bash/zsh)。 Hacker News 留言多半把它視為「老但實用」的咒語:有人笑說自己偶爾會在目錄裡看到一個叫 `1` 的檔案,就是把 `2>&1` 寫成 `2>1` 的副作用;也有人提到近來大型語言模型(LLM, Large Language Model)在呼叫命令列工具時很常自動加上它,因為把錯誤訊息混進同一串流,對機器後續解析或記錄比較省事,而對人類熟手來說也早已是肌肉記憶。 另一派留言則聚焦在「語法為何這麼晦澀」與 shell 的歷史包袱:有人批評以數字暴露檔案描述子太像把底層細節直接丟給使用者,期待有更語意化的寫法(甚至有人提議類似 `&stderr>&stdout` 的可讀語法);也有人反駁當年使用者多是程式設計者/系統管理者,有限字元集下需要區分「檔名」與「描述子」才用 `&`,而簡單、可靠的工具之所以能活數十年正是因為這些設計。留言也補充了實務技巧與陷阱:推薦用 ShellCheck 這類檢查工具避免管線與重導向順序搞錯;以及利用額外描述子(例如 fd 3)把「給機器看的輸出」與「給人看的提示/記錄」分流,甚至有把 JSON 放在 fd 3 作為較穩定的機器可解析通道的做法,同時提醒 `|` 是管線運算子而非單純重導向,會影響整行命令的切分與套用位置。 👥 72 則討論、評論 💬 https://news.ycombinator.com/item?id=47171233