Как работают `>` и `>>`?

9

Я попытался revсоздать файл, а затем cat > same_fileпередать его, но он превратился в пустой файл.

Пока я пытался rev file.txt | cat > file2.txt && mv file.txt file2.txt;это сработало.

Даже rev file.txt | cat >> file.txt;работал.

Но когда я попробовал rev file.txt | cat > file.txtэто не удалось.

Vintux
источник
Вы также можете оставить catвот так: rev file.txt > file2.txt && mv file2.txt file.txt. Это излишнее использованиеcat . Оставляя это вне, вы избавляетесь от создания дополнительного процесса.
Матега

Ответы:

19

Основное, что вам нужно понять в этом случае между двумя способами перенаправления (> и >>):

>

Перенаправляет и перезаписывает информацию, на которую она была указана. Это происходит при получении любой информации через канал "|"

>>

Перенаправляет и объединяет информацию, на которую он был указан. Это происходит при получении любой информации через канал "|"

В обоих случаях, если файл не существует, он будет создан вместо. Только в «>>» информация будет объединена, если вы снова запустите ее в том же файле. С помощью «>» вы просто перезаписываете все, что делали при первом запуске.

Но здесь есть дело, когда используется тот же входной файл, что и выходной файл. В этом конкретном случае, если вы используете «>», вы удалите информацию, которую «входная» часть должна проанализировать, так как выходной файл будет «перезаписывать ее». Итак, в:

rev file.txt | cat > file.txt

Что на самом деле происходит в «объяснении замедленного движения»:

  1. revготовится отменить содержание file.txtи отправить его в трубу
  2. Пока revотправляет информацию в канал, канал направляет ее напрямую cat.
  3. В то время как catполучает информацию , которую он будет автоматически применить его к file.txtон был установлен с.
  4. Ключевое слово здесь - «время», потому что все происходит одновременно. Пожалуйста, посмотрите превосходные комментарии Эмиля ниже, чтобы глубже понять эту часть.
  5. catне будет ждать, revчтобы передать весь файл. Он просто запустится в ту минуту, когда к нему поступит первая часть информации, а это означает, что в зависимости от того, какой символ вы использовали, он откроет соединение file.txt.
  6. В этом случае, так как вы использовали > вместо >> , оболочка будет обрезать выходной файл, что означает, что она откроет и очистит информацию в file.txtожидании новой информации, чтобы добраться до него. С >> он установит соединение file.txtи будет ждать новой информации в последней обнаруженной строке.
  7. Поскольку информация уже была очищена file.txtс помощью > , revон попытается выполнить свою работу и ничего не получит, потому что catудалил все в процессе подготовки к новой информации.

Так почему другие работают после прочтения выше? Из-за этого:

rev file.txt | cat > file2.txt && mv file.txt file2.txt

Здесь вы отправляете сообщение коту, который отправляет информацию в другой файл. В этом случае обработанный входной файл file.txtне совпадает с выходным файлом file2.txt. После того, что вы буквально перезаписывать все file2.txtс file.txt, так что весь процесс сделан catбыл удален. По сути, вся строка может быть упрощена, например, cp file.txt file2.txtпотому что она делает то же самое, так file2.txtкак в конце теряет revи перезаписывается mvкомандой.

rev file.txt | cat >> file.txt

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

Луис Альварадо
источник
5
Файл не урезан кошкой. Он усекается оболочкой до того , как какая-либо команда в конвейере будет запущена.
Эмиль Йержабек
Правильно, искал более простые слова для объяснения. Поскольку это немного сложно объяснить, если ОП не знает, что это за оболочка и все такое. Попытка сделать это как можно более дружелюбным.
Луис Альварадо
1
Ну, на самом деле не имеет значения, что это делает оболочка, но что вы не правильно выбрали время. Усечение не произойдет на шаге 6, но на шаге 0 rev file.txt | cat --bogus-option > file.txtбудет также усечен файл, даже если cat не будет пытаться открыть его.
Эмиль Йержабек,
@ EmilJeřábek Вы правы. Тем не менее, пользователям, которые не знают, как он себя ведет, будет легче, если мы будем идти шаг за шагом только с командами. Также ваш пример по-прежнему отправляет информацию в тот же файл, поэтому bash прочитает всю эту строку, увидит вывод и все еще откроет И обрежет ее. Ошибка - это просто вывод stderr в stdout.
Луис Альварадо
4
См. Также moreutils , фантастическую коллекцию инструментов (доступную из репозитория пакетов as moreutils), которая включает в spongeсебя инструмент, специально разработанный для сценария перезаписи входного файла. Например, существует rev file.txt >file2.txt && mv file2.txt file.txtобходной путь rev file.txt | sponge file.txt, который будет работать правильно, даже если имя уже есть file2.txt.
Даниэль Вагнер
9

Когда оболочка видит перенаправление, она сначала открывает соответствующие файлы перед выполнением любой из задействованных команд. Таким образом, когда вы делаете:

foo file.txt | bar > file.txt

Перенаправление file.txtвызывает его обрезание перед foo запуском и чтением file.txt. Кстати, вот почему вы не можете сделать:

sed 'blah' file.txt > file.txt

И почему sedесть возможность редактирования на месте.

Наконец, делая:

.. | cat > file.txt

это бесполезно использование кошки , особенно так , если вы пытаетесь прочитать от file.txtранее.

Если вы хотите перевернуть файл на месте, ярлыки отсутствуют . Вы можете использовать трюки sedили awkс редактированием на месте.

Мур
источник
3

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

В вашем случае вывод идет в файл file.txt, если этот файл уже существует, он перезаписывается, если не создается.

>>является оператором добавления, если он file.txtуже существует, вывод добавляется в конец файла. если файл не существует, он создается, и вывод записывается в новый файл, так же как >(перенаправитель).

Кен Моллеруп
источник
ОП, кажется, понял это. Беспорядок , кажется, происходит только из одного файла находящегося на обеих сторонах >и >>операторов.
Bzlm
0

Вы можете использовать Vim в режиме Ex:

ex -sc '%!rev' -cx file.txt
  1. % выбрать все строки

  2. ! Команда Run

  3. x сохранить и закрыть

Стивен Пенни
источник