Файловые дескрипторы & 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.

27 голосов | спросил Ricko M 25 Mayam11 2011, 02:08:57

1 ответ


39

Во-первых, обратите внимание, что синтаксис закрытия - 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 на этом сайте .

ответил Gilles 25 Mayam11 2011, 03:39:14

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132