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

Shell 有時(shí)會(huì)引用使用文件描述符(fd)的文件。我們一般使用文件描述符(fd)的范圍是數(shù)字 0~9。重定向時(shí)大于 9 的文件描述符要謹(jǐn)慎使用,因?yàn)樗鼈兛赡芘c Shell 內(nèi)部使用的文件描述符沖突。

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

有些文件描述符是在 Shell 啟動(dòng)時(shí)被建立的,這就是我們前面介紹的標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)注錯(cuò)誤(0、1、2)文件描述符。

實(shí)例:使用 exec 命令

Bash 的內(nèi)部命令 exec 的功能之一就是允許我們操作文件描述符。如果在 exec 之后沒有指定命令,則 exec 命令之后的重定向?qū)⒏漠?dāng)前 Shell 的文件描述符。

例如,在命令 “exec 2> file” 之后運(yùn)行的所有命令,都會(huì)將其產(chǎn)生的錯(cuò)誤信息發(fā)送到文件 file 中,就像你的命令在腳本 myscript.sh 中,而你運(yùn)行的是 “./myscript.sh >2 file”。

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

exec 2> errors.log

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

#! /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
運(yùn)行結(jié)果

從上面的輸出結(jié)果我們可以看到,read 語句并沒有執(zhí)行:因?yàn)槲覀儗⒅付ǖ奈募囟ㄏ虻搅?while 循環(huán)的標(biāo)準(zhǔn)輸入(文件描述符 0),即我們指定的文件將被打開以用于標(biāo)準(zhǔn)輸入的讀取,而循環(huán)中的所有命令包括 read 命令都會(huì)繼承這個(gè)文件描述符(這里是標(biāo)準(zhǔn)輸入),因此 read 將從重定向后的標(biāo)準(zhǔn)輸入讀取,而不是從默認(rèn)的標(biāo)準(zhǔn)輸入設(shè)備(鍵盤)讀取。

而此時(shí),我們就可以使用 exec 命令對(duì)腳本稍加改動(dòng),來實(shí)現(xiàn)我們想要的功能,改動(dòng)后的腳本將類似如下所示:

#! /bin/bash

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

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

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

# 關(guān)閉文件描述符 3
exec 3<&-

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

上述腳本的運(yùn)行效果

運(yùn)行結(jié)果

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容