Вопрос или проблема
Предположим, у нас есть папка с двумя файлами:
- 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”?
С уважением, Бастиан
Две важные вещи:
- В ваших примерах
echo
всегда выполняется передcat
. - Каждая переадресация
> 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
В этом ответе мы подробно рассмотрим работу операторов перенаправления >
и <
в командной оболочке Bash, особенно в контексте использования в скобках. Мы проанализируем ряд примеров и объясним, почему поведение команд может отличаться в зависимости от ситуации.
Основы: Операторы перенаправления
- Оператор
>
: Используется для перенаправления стандартного вывода команды в файл. Если файл уже существует, он будет перезаписан. Если его нет, файл будет создан. - Оператор
<
: Позволяет перенаправить содержимое файла на стандартный ввод команды. Это значит, что команда будет получать данные не из терминала, а из указанного файла.
Примеры и пояснения
Рассмотрим ваши примеры и разберём, как действуют операторы перенаправления:
-
Пример 1:
(echo "test" > file_test; < file_empty cat) > file_out
Результат:
file_out
остается пустым.В этом случае:
echo "test" > file_test
записывает строку "test" вfile_test
.- Затем
< file_empty cat
пытается прочитать содержимоеfile_empty
(который пустой) и перенаправить вывод вfile_out
. Поскольку файл пуст,file_out
остается пустым.
-
Пример 2:
(echo "test" > file_test; < file_in cat) > file_test
Результат:
file_test
содержит "something".Здесь:
- Первый оператор
echo
записывает "test" вfile_test
. - Затем
< file_in cat
читает содержимоеfile_in
, в котором есть строка "something", и записывает её вfile_test
, перезаписывая "test".
- Первый оператор
-
Пример 3:
(echo "test" > file_test; < file_empty cat) > file_test
Результат:
file_test
содержит "test".В этом случае:
- Сначала выполняется
echo "test" > file_test
, и в файл записывается "test". - Далее,
< file_empty cat
выполняется, но, посколькуfile_empty
пустой,cat
ничего не добавляет. Однакоfile_test
при этом уже открыт для записи, и, по завершении команды, возвращается к содержимому "test".
- Сначала выполняется
Ключевые моменты
-
Отдельные дескрипторы файлов: Каждый оператор
>
создает независимый дескриптор файла. При этомecho
иcat
не взаимодействуют друг с другом, поскольку у них разные открытые дескрипторы. -
Время выполнения команд:
echo
всегда выполняется передcat
. Это значит, что то, чтоecho
записывает в файл, будет перезаписано, еслиcat
также открывает этот файл. -
Содержимое файлов: Если команда
cat
читает из пустого файла, она не вносит изменений в целевой файл, тогда как если она читает из непустого, то она может перезаписать его содержимое.
Заключение
Понимание операторов перенаправления в Bash — это ключ к эффективному управлению вводом и выводом в командной оболочке. Каждый раз, когда вы создаете новый дескриптор файла с помощью >
, вы фактически создаете новое пространство для вывода, независимое от других процессов, которые также могут записывать в файлы. Это понимание позволяет избежать неожиданных результатов и лучше контролировать данные в ваших скриптах и командах.
SEO Оптимизация
Ключевые слова, заголовки и краткое изложение примеров в статье помогут улучшить видимость вашего контента в поисковых системах, делая его более доступным для тех, кто ищет информацию о Bash и операторах перенаправления.