16.1. С помощью команды exec


16.1. С помощью команды exec

Команда exec <filename перенаправляет ввод со stdin на файл. С этого момента весь ввод, вместо stdin (обычно это клавиатура), будет производиться из этого файла. Это дает возможность читать содержимое файла, строку за строкой, и анализировать каждую введенную строку с помощью sed и/или awk.

Пример 16-1. Перенаправление stdin с помощью exec

  1. #!/bin/bash
  2. # Перенаправление stdin с помощью 'exec'.
  3. exec 6<&0          # Связать дескр. #6 со стандартным вводом (stdin).
  4.                    # Сохраняя stdin.
  5. exec < data-file   # stdin заменяется файлом "data-file"
  6. read a1            # Читается первая строка из "data-file".
  7. read a2            # Читается вторая строка из "data-file."
  8. echo
  9. echo "Следующие строки были прочитаны из файла."
  10. echo "-----------------------------------------"
  11. echo $a1
  12. echo $a2
  13. echo; echo; echo
  14. exec 0<&6 6<&-
  15. #  Восстанавливается stdin из дескр. #6, где он был предварительно сохранен,
  16. #+ и дескр. #6 закрывается ( 6<&- ) освобождая его для других процессов.
  17. #
  18. # <&6 6<&-    дает тот же результат.
  19. echo -n "Введите строку  "
  20. read b1  # Теперь функция "read", как и следовало ожидать, принимает данные с обычного stdin.
  21. echo "Строка, принятая со stdin."
  22. echo "--------------------------"
  23. echo "b1 = $b1"
  24. echo
  25. exit 0

Аналогично, конструкция exec >filename перенаправляет вывод на stdout в заданный файл. После этого, весь вывод от команд, который обычно направляется на stdout, теперь выводится в этот файл.

Пример 16-2. Перенаправление stdout с помощью exec

  1. #!/bin/bash
  2. # reassign-stdout.sh
  3. LOGFILE=logfile.txt
  4. exec 6>&1           # Связать дескр. #6 со stdout.
  5.                     # Сохраняя stdout.
  6. exec > $LOGFILE     # stdout замещается файлом "logfile.txt".
  7. # ----------------------------------------------------------- #
  8. # Весь вывод от команд, в данном блоке, записывается в файл $LOGFILE.
  9. echo -n "Logfile: "
  10. date
  11. echo "-------------------------------------"
  12. echo
  13. echo "Вывод команды \"ls -al\""
  14. echo
  15. ls -al
  16. echo; echo
  17. echo "Вывод команды \"df\""
  18. echo
  19. df
  20. # ----------------------------------------------------------- #
  21. exec 1>&6 6>&-      # Восстановить stdout и закрыть дескр. #6.
  22. echo
  23. echo "== stdout восстановлено в значение по-умолчанию == "
  24. echo
  25. ls -al
  26. echo
  27. exit 0

Пример 16-3. Одновременное перенаправление устройств, stdin и stdout, с помощью команды exec

  1. #!/bin/bash
  2. # upperconv.sh
  3. # Преобразование символов во входном файле в верхний регистр.
  4. E_FILE_ACCESS=70
  5. E_WRONG_ARGS=71
  6. if [ ! -r "$1" ]     # Файл доступен для чтения?
  7. then
  8.   echo "Невозможно прочитать из заданного файла!"
  9.   echo "Порядок использования: $0 input-file output-file"
  10.   exit $E_FILE_ACCESS
  11. fi                   #  В случае, если входной файл ($1) не задан
  12.                      #+ код завершения будет этим же.
  13. if [ -z "$2" ]
  14. then
  15.   echo "Необходимо задать выходной файл."
  16.   echo "Порядок использования: $0 input-file output-file"
  17.   exit $E_WRONG_ARGS
  18. fi
  19. exec 4<&0
  20. exec < $1            # Назначить ввод из входного файла.
  21. exec 7>&1
  22. exec > $2            # Назначить вывод в выходной файл.
  23.                      # Предполагается, что выходной файл доступен для записи
  24.                      # (добавить проверку?).
  25. # -----------------------------------------------
  26.     cat - | tr a-z A-Z   # Перевод в верхний регистр
  27. #   ^^^^^                # Чтение со stdin.
  28. #           ^^^^^^^^^^   # Запись в stdout.
  29. # Однако, и stdin и stdout были перенаправлены.
  30. # -----------------------------------------------
  31. exec 1>&7 7>&-       # Восстановить stdout.
  32. exec 0<&4 4<&-       # Восстановить stdin.
  33. # После восстановления, следующая строка выводится на stdout, чего и следовало ожидать.
  34. echo "Символы из \"$1\" преобразованы в верхний регистр, результат записан в \"$2\"."
  35. exit 0