文件描述符和Shell脚本


32

我很难理解一个人如何在shell脚本中使用文件描述符。

我知道诸如

exec 5 > /tmp/foo

因此,将fd 5附加到foo进行编写。

exec 6 < /tmp/bar

...阅读。

exec 5>&-

…关闭fd。

现在这是做什么的?

#!/bin/bash

exec 5 > /tmp/foo 
exec 6 < /tmp/bar 

cat <&6 | while read a
do
     echo $a >&5
done

据我了解,&5关闭FD,那么每次调用后输出仍如何成功重定向?

这是来自的复制面食:这里

它声称通过简单的echo $a > file方法使用它会使其更快,但是我无法理解。我将不胜感激任何链接到体面的教程。我用google的功能似乎使我失望。

Answers:


44

首先,请注意,用于关闭的语法是5>&-6<&-,具体取决于正在读取文件描述符以进行写入还是读取。该博客文章中似乎存在拼写错误或格式错误。

这是评论的脚本。

exec 5>/tmp/foo       # open /tmp/foo for writing, on fd 5
exec 6</tmp/bar       # open /tmp/bar for reading, on fd 6
cat <&6 |             # call cat, with its standard input connected to
                      # what is currently fd 6, i.e., /tmp/bar
while read a; do      # 
  echo $a >&5         # write to fd 5, i.e., /tmp/foo
done                  # 

这里没有关门。由于在此简单示例中所有输入和输出都将移至同一位置,因此不需要使用额外的文件描述符。你可以写

cat </tmp/bar |
while read a; do
  echo $a
done >/tmp/foo

当您要依次写入多个文件时,使用显式文件描述符将很有用。例如,考虑一个脚本,该脚本将数据输出到数据输出文件,并将数据记录到日志文件,并可能还会显示错误消息。这意味着三个输出通道:一个用于数据,一个用于日志,一个用于错误。由于只有两个标准描述符用于输出,因此需要第三个。您可以调用exec以打开输出文件:

exec >data-file
exec 3>log-file
echo "first line of data"
echo "this is a log line" >&3

if something_bad_happens; then echo error message >&2; fi
exec >&-  # close the data output file
echo "output file closed" >&3

当您在循环中进行重定向时(例如文件开头是空的),就会出现关于效率的评论:

while …; do echo $a >>/tmp/bar; done

在每次迭代时,程序都会打开/tmp/bar,搜索到文件的末尾,追加一些数据并关闭文件。一劳永逸地打开文件更有效:

while …; do echo $a; done >/tmp/bar

当在不同时间发生多个重定向时,调用exec执行重定向而不是将块包装在重定向中将变得很有用。

exec >/tmp/bar
while …; do echo $a; done

通过浏览io-redirection此站点上的标签,您还将找到其他一些重定向示例


1
两种关闭文件描述符的语法实际上都做同样的事情。
user1338062 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.