0 (stdin)、1 (stdout)、2 (stderr)。ulimit -n 查看/設定進程最大 FD 數 (預設 1024)。exec <重導向操作> # 影響當前 Shell 後續所有命令
exec <操作符><目標> # 任意 FD 操作
exec 3<> hello.txt # FD 3 開啟 hello.txt 讀寫 (若不存在會建立)
echo "hello exec" >&3 # 寫入 FD 3 (從檔案開頭覆蓋)
echo "hello world" >&3 # 續寫
exec 3>&- # 關閉 FD 3 寫入 (實際上也無法再讀)
# exec 3<&- # 僅關閉讀取
exec 1> log.txt # 後續所有 echo/printf 等輸出導向 log.txt
echo "this goes to log.txt"
# 恢復需見案例 3
exec 100>&1 # ① 將 FD 100 複製標準輸出 (備份)
exec 1> log.txt # ② 重導向 stdout 到檔案
echo "in log.txt"
exec 1>&100 100>&- # ③ 恢復 stdout (1 指向 100),關閉備份 FD 100
echo "back to terminal"
原理: 100>&1 使 FD 100 指向 FD 1 當前指向的檔案表項;1>&100 再將 FD 1 指回該項。
exec 100<&0 # 備份 stdin
exec < input.txt # stdin 來自檔案
read line1; echo "Line1: $line1"
read line2; echo "Line2: $line2"
exec 0<&100 100<&- # 恢復 stdin
read -p "Manual input: " custom
#!/bin/bash
OUTFILE="out.txt"; INFILE="in.txt"
: > "$OUTFILE" # 清空輸出檔
exec 4>&1 # 備份 stdout 到 FD 4
exec 1> "$OUTFILE" # stdout 導向輸出檔
while IFS= read -r line; do
echo "$line: processed"
done < "$INFILE"
exec 1>&4 4>&- # 恢復 stdout,關閉 FD 4
echo "Done, check $OUTFILE"
find <路徑> <條件> -exec <命令> {} \;
# {} 會被替換為找到的檔案路徑
# \; 結束 -exec (需轉義防止 Shell 解釋)
# + 替換 \; 可批次傳遞多個檔案 (如 xargs),效率更高
# 1. 找所有 .txt 並 grep "bin"
find . -name "*.txt" -exec grep "bin" {} \;
# 2. 刪除所有 .tmp (謹慎!)
find . -name "*.tmp" -exec rm {} \;
# 3. 批次修改擁有者
find /data -type f -exec chown www-data:www-data {} +
# 4. 壓縮超過 30 天的日誌
find /var/log -name "*.log" -mtime +30 -exec gzip {} +
# 5. 複製特定結構到備份目錄
find . -name "*.conf" -exec cp --parents {} /backup \;
| 陷阱 | 說明 | 對策 |
|---|---|---|
| FD 洩漏 | 迴圈中開啟 FD 未關閉,耗盡限額 | 嚴格配對 exec N>&-/exec N<&-,或用 {var}<>file (Bash 4.1+) 自動分配未用 FD |
| 子 Shell 不繼承 exec 修改 | (exec 1>file; echo hi) 不影響父 Shell | 在主 Shell 執行 exec,或用函數而非子 Shell |
| 管道與 exec 衝突 | exec 1>file | cmd 管道優先 | 避免同一命令混用管道與 exec 重導向 |
| FD 數字衝突 | 硬編碼 3,4,5 可能與其他部分衝突 | 用 exec {var}>file 讓 Shell 自動分配 (Bash 4.1+) |
exec {LOG_FD}> log.txt
echo "Auto FD: $LOG_FD" >&$LOG_FD
exec {LOG_FD}>&- # 關閉
# 讀取同理
exec {IN_FD}< input.txt
read line <&$IN_FD
exec {IN_FD}<&-
exec 配合檔案描述符操作,是 Shell 腳本處理複雜 I/O 重導向、持久化檔案存取、實現雙向通訊的核心武器。掌握「備份 → 重導向 → 恢復」三步曲、善用自動分配 FD、結合 find -exec + 批次處理,能編寫出高效、健壯、易維護的自動化腳本。