Shell 有時會引用使用文件描述符(fd)的文件扑媚。我們一般使用文件描述符(fd)的范圍是數(shù)字 0~9盆赤。重定向時大于 9 的文件描述符要謹(jǐn)慎使用霉祸,因為它們可能與 Shell 內(nèi)部使用的文件描述符沖突脐湾。
文件描述符可以包含多個數(shù)字位乳乌。例如捧韵,文件描述符 001 和 01 與文件描述符 1 是相同的。多種操作(例如汉操,exec 命令)都可以將文件描述符與特定的文件聯(lián)系起來再来。
有些文件描述符是在 Shell 啟動時被建立的,這就是我們前面介紹的標(biāo)準(zhǔn)輸入磷瘤、標(biāo)準(zhǔn)輸出和標(biāo)注錯誤(0芒篷、1、2)文件描述符采缚。
實例:使用 exec 命令
Bash 的內(nèi)部命令 exec 的功能之一就是允許我們操作文件描述符针炉。如果在 exec 之后沒有指定命令,則 exec 命令之后的重定向?qū)⒏漠?dāng)前 Shell 的文件描述符扳抽。
例如篡帕,在命令 “exec 2> file” 之后運行的所有命令,都會將其產(chǎn)生的錯誤信息發(fā)送到文件 file 中贸呢,就像你的命令在腳本 myscript.sh 中镰烧,而你運行的是 “./myscript.sh >2 file”。
比如楞陷,如果你想記錄腳本中的命令產(chǎn)生的錯誤信息怔鳖,就可以在腳本的開頭使用類似如下的命令:
exec 2> errors.log
下面我們來看一個腳本文件,在這個腳本中我們想要順序地讀取文件中的每一行猜谚,并在打印每一行之后败砂,等待用戶輸入任意鍵后繼續(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
從上面的輸出結(jié)果我們可以看到,read 語句并沒有執(zhí)行:因為我們將指定的文件重定向到了 while 循環(huán)的標(biāo)準(zhǔn)輸入(文件描述符 0)昌犹,即我們指定的文件將被打開以用于標(biāo)準(zhǔn)輸入的讀取坚芜,而循環(huán)中的所有命令包括 read 命令都會繼承這個文件描述符(這里是標(biāo)準(zhǔn)輸入),因此 read 將從重定向后的標(biāo)準(zhǔn)輸入讀取斜姥,而不是從默認(rèn)的標(biāo)準(zhǔn)輸入設(shè)備(鍵盤)讀取鸿竖。
而此時,我們就可以使用 exec 命令對腳本稍加改動铸敏,來實現(xiàn)我們想要的功能缚忧,改動后的腳本將類似如下所示:
#! /bin/bash
if [ $# -lt 1 ]; then
echo "Usage: $0 FILEPATH"
exit
fi
# 將腳本的第一個參數(shù)作為輸入文件,并制定一個文件描述符 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ù)。
上述腳本的運行效果
本文參考自 《Linux Shell命令行及腳本編程實例詳解 》