Shell 允许你给一个输入文件或输出文件指定一个文件描述符。这样可以提高文件读取和写入的性能。这类文件描述符被称为用户自定义文件描述符。
给一个输入文件指定一个文件描述符的语法如下所示:
exec [n]< file
其中,[n] 即文件描述符,如果不指定 n,则表示标准输入(即文件描述符 0)。
上述的输入重定向会在文件描述符 n 上打开一个用于读取的文件 file。
例如,执行如下命令,将文件描述符 3 指定给文件 /etc/passwd 以用于从中读取数据:
exec 3< /etc/passwd
现在我们就可以在文件描述符 3 上读取此文件的内容,比如,使用 grep 命令来查找指定账号的信息:
grep toby <& 3
上述命令中,我们使用了操作符 “<&”,它也是一种重定向操作符,用于复制输入文件描述符。其语法如下所示:
[n] <& word
如果 word 是一个数字,则用 n 表示的文件描述符被作为文件描述符 word 的副本。如果数字 word 指定的文件描述符没有打开以用于读取,则会发生重定向错误。如果没有指定 n,则默认为标准输入。
所以,在上述的 grep 命令中,是将文件描述符 3 复制到标准输入,而文件 /etc/passwd 又是在文件描述符 3 上打开以用于被命令读取,因此,grep 命令读取的实际是文件描述符 3 的内容。
在下面的脚本中,我们从指定的文件描述符来读取文件的内容:
#! /bin/bash
if [ $# -ne 1 ] || [ ! -f $1 ]; then
echo "Usage: $0 <FILEPATH>"
exit 1
fi
# 将脚本的第一个参数作为输入文件,并制定一个文件描述符 3
exec 3< $1
cat <& 3
# 关闭文件描述符 3
exec 3<&-
运行结果:
下面我们再通过一个实例,来进一步学习使用 exec 命令指定用于输入的文件描述符:
#! /bin/bash
# 将标准输入复制到文件描述符 6,保存标准输入
exec 6<&0
# 将文件 /etc/hosts 重定向到标准输入
exec < /etc/hosts
# 读取 /etc/hosts 的第一行,并将读取的内容存入变量 a1
read a1
read a2
echo
echo "Following lines read from file."
echo "-------------------------------"
echo $a1
echo $a2
echo; echo; echo
# 现在从文件描述符 6 中恢复标准输入,并关闭文件描述符 6 以释放给其他进行使用
exec <&6 6<&-
echo -n "Enter data: "
read b1
echo "Input read from stdin."
echo "------------------------------"
echo "b1 = $b1"
echo
此脚本的运行结果:
本文参考自 《Linux Shell命令行及脚本编程实例详解 》