Дескриптори файлів та сценарії оболонки


32

Мені дуже важко зрозуміти, як використовуються дескриптори файлів у скриптах оболонки.

Я знаю основи, такі як

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 збивати мене.

Відповіді:


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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.