Понимание bash ” с круглыми скобками

Вопрос или проблема

Предположим, у нас есть папка с двумя файлами:

  • file_empty, который ничего не содержит
  • file_in, содержащий только одну строку: “что-то”

Смотрите результат следующих примеров:

(echo "test" > file_test; < file_empty cat) > file_out

в результате file_out будет пустым.

(echo "test" > file_test; < file_in cat) > file_test

в результате file_test будет содержать “что-то”.

Наконец,

(echo "test" > file_test; < file_empty cat) > file_test

в результате file_test будет содержать “test”.

В последнем примере я ожидал, что file_test будет пустым,
как в первом примере.
Не могли бы вы объяснить мне, почему он будет содержать “test”?

Две важные вещи:

  1. В ваших примерах echo всегда выполняется перед cat.
  2. Каждое перенаправление > file_test создает независимое открытое описание файла.

Ваш первый пример прост: echo записывает в file_test, затем cat копирует содержимое file_empty в file_out.

Во втором и третьем примерах file_test открывается и усекается дважды. Сначала “внешний” > file_test открывает и усекает файл, затем другое > file_test открывает и усекает файл для echo; только потом запускается echo, и наконец запускается cat.

В результате echo записывает в file_test с начала файла, а cat записывает в file_test независимо с начала файла. Эти два инструмента не разделяют открытое описание файла, поэтому действие записи echo не перемещает позицию в файле для cat. Последний инструмент (перезаписывает) файл с начала, а не с места, где echo завершился.

В частности, во втором примере echo записывает test в файл, затем cat помещает что-то в файл с его начала, перезаписывая test.

В третьем примере echo записывает test в файл, затем cat помещает пустую строку в файл с его начала, не перезаписывая ничего (поскольку размер пустой строки равен нулю байт).

Чтобы лучше понять, что происходит, рассмотрим это:

(echo "1234567890интересно" > file_test; < file_in cat) > file_test

Сначала echo записывает 12… в файл, затем cat помещает что-то в файл с его начала, перезаписывая 12…89 на что-то и 0 на завершающий символ новой строки из file_in (я предполагаю, что строка, в которой написано что-то, правильно завершается в file_in). Содержимое file_test теперь:

что-то
интересно

(с завершающим символом новой строки после интересно, добавленным echo в первую очередь).

Иначе обстоит дело с

(echo "1234567890интересно" > file_test; < file_in cat) >> file_test

потому что >> по сути означает “всегда перемещаться в конец файла”. На этот раз cat записывает с того места, где echo завершился, потому что именно здесь заканчивается файл. Попробуйте. Результат будет:

1234567890интересно
что-то

(с завершающим символом новой строки из file_in).

Также, если два инструмента действительно разделяют открытое описание файла (созданное с помощью >), тогда echo будет перемещать позицию в файле для cat:

(echo "1234567890интересно"; < file_in cat) > file_test

Результат снова будет

1234567890интересно
что-то

(с завершающим символом новой строки из file_in).

Ответ или решение

Объяснение работы операторов > и < в bash с использованием скобок

В мире Linux и bash-подобных оболочек управление вводом и выводом является важной концепцией, позволяющей управлять данными, которые передаются между процессами и файлами. В данном контексте мы рассмотрим работу операторов перенаправления > (вывод) и < (ввод) в сочетании с подстановочными выражениями, которые заключены в скобки.

Описание Примера

Вы рассматриваете два файла:

  • file_empty, который не содержит никаких данных.
  • file_in, содержащий одну строку — "something".

Рассмотрим несколько примеров использования операторов перенаправления и разберем их результаты.

Пример 1

(echo "test" > file_test; < file_empty cat) > file_out

Результат: file_out остается пустым.

Объяснение:

  1. Команда echo "test" создает файл file_test и записывает в него строку "test".
  2. Команда cat, которая принимает ввод из file_empty, выполняется, но так как файл пустой, в file_out ничего не записывается.
  3. Поскольку каждый оператор > создает новую файловую дескриптору, операции вывода не влияют друг на друга.

Пример 2

(echo "test" > file_test; < file_in cat) > file_test

Результат: file_test теперь содержит "something".

Объяснение:

  1. В первой части выражения команда echo запускается и открывает файл file_test, в который записывается "test". Однако в этот момент он уже открыт и может быть обрезан.
  2. Затем команда cat, которая читает из file_in, открывает file_test и перезаписывает его содержимое, начиная с начала файла, чем фактически заменяет "test" на "something".

Пример 3

(echo "test" > file_test; < file_empty cat) > file_test

Результат: file_test будет содержать "test".

Объяснение:

  1. Сначала команда echo записывает "test" в file_test.
  2. Затем команда cat, которая читает из file_empty, открывает файл file_test для записи и не находит ничего для записи, следовательно, не дорожит содержимым из-за того, что в file_empty нет данных. Это приводит к тому, что существующее содержимое остаётся неизменным.

Ключевые Пункты в Работе с Операторами

  1. Временные файловые дескрипторы: Каждый раз, когда вы используете >, создается новый временный файловый дескриптор. Это означает, что операции, выполняемые в рамках одной группы команд, могут не взаимодействовать так, как это может ожидаться.

  2. Порядок выполнения: Ваша логика может ошибаться при ожидании, что записи в файл будут происходить последовательно. Однако, поскольку команды внутри скобок работают одновременно, важно понимать, что вывод разных команд может перезаписывать файл независимо друг от друга.

  3. Текущая позиция в файле: Позиция записи в файл при использовании > всегда начинается с начала, в отличие от операций с использованием >>, которые добавляют данные в конец файла.

  4. Функции cat и echo: Обе эти команды имеют свою специфику работы с файлами, что также влияет на результат выполнения.

Заключение

Понимание работы с операторами перенаправления в bash критично для правильного управления вводом и выводом данных. На примерах выше мы видели, как порядок выполнения команд и создание отдельных дескрипторов файлов может влиять на результат. Запоминайте эти ключевые моменты, чтобы избежать неожиданных результатов в процессе работы с файловыми операциями в bash.

Оцените материал
Добавить комментарий

Капча загружается...