Shell 重定向(四):文件描述符

Shell 有時會引用使用文件描述符(fd)的文件。我們一般使用文件描述符(fd)的范圍是數字 0~9。重定向時大于 9 的文件描述符要謹慎使用,因為它們可能與 Shell 內部使用的文件描述符沖突。

文件描述符可以包含多個數字位。例如,文件描述符 001 和 01 與文件描述符 1 是相同的。多種操作(例如,exec 命令)都可以將文件描述符與特定的文件聯系起來。

有些文件描述符是在 Shell 啟動時被建立的,這就是我們前面介紹的標準輸入、標準輸出和標注錯誤(0、1、2)文件描述符。

實例:使用 exec 命令

Bash 的內部命令 exec 的功能之一就是允許我們操作文件描述符。如果在 exec 之后沒有指定命令,則 exec 命令之后的重定向將更改當前 Shell 的文件描述符。

例如,在命令 “exec 2> file” 之后運行的所有命令,都會將其產生的錯誤信息發送到文件 file 中,就像你的命令在腳本 myscript.sh 中,而你運行的是 “./myscript.sh >2 file”。

比如,如果你想記錄腳本中的命令產生的錯誤信息,就可以在腳本的開頭使用類似如下的命令:

exec 2> errors.log

下面我們來看一個腳本文件,在這個腳本中我們想要順序地讀取文件中的每一行,并在打印每一行之后,等待用戶輸入任意鍵后繼續。

#! /bin/bash

if [ $# -lt 1 ]; then
    echo "Usage: $0 FILEPATH"
    exit
fi

file=$1

while read -r line
do
    echo $line
    read -p "Press any key" -n 1
done < $file
運行結果

從上面的輸出結果我們可以看到,read 語句并沒有執行:因為我們將指定的文件重定向到了 while 循環的標準輸入(文件描述符 0),即我們指定的文件將被打開以用于標準輸入的讀取,而循環中的所有命令包括 read 命令都會繼承這個文件描述符(這里是標準輸入),因此 read 將從重定向后的標準輸入讀取,而不是從默認的標準輸入設備(鍵盤)讀取。

而此時,我們就可以使用 exec 命令對腳本稍加改動,來實現我們想要的功能,改動后的腳本將類似如下所示:

#! /bin/bash

if [ $# -lt 1 ]; then
    echo "Usage: $0 FILEPATH"
    exit
fi

# 將腳本的第一個參數作為輸入文件,并制定一個文件描述符 3
exec 3< $1

while read -u 3 line
do
    echo $line
    read -p "Press any key: " -n 1
done

# 關閉文件描述符 3
exec 3<&-

在上述腳本中,我們使用的 “read -u 3 line” 命令,為 read 指定從指定的描述符中讀取數據。

上述腳本的運行效果

運行結果

本文參考自 《Linux Shell命令行及腳本編程實例詳解

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容