79

Рассмотрим оболочку типа Bash или sh. Основное различие между > и >> проявляется в случае, когда целевой файл существует:

  • > обрезает файл до нулевого размера, затем записывает;
  • >> не усекает, он пишет (добавляет) в конец файла.

Если файл не существует, он создается с нулевым размером; затем написано Это верно для обоих операторов. Может показаться, что операторы эквивалентны, когда целевой файл еще не существует.

Они действительно?

1 ответ1

106

ТЛ; др

Нет. >> по сути "всегда ищет конец файла", в то время как > поддерживает указатель на последнее записанное местоположение.


Полный ответ

(Примечание: все мои тесты выполнены на Debian GNU/Linux 9).

Еще одно отличие

Нет, они не эквивалентны. Есть еще одно отличие. Он может проявляться независимо от того, существовал ли ранее целевой файл или нет.

Чтобы наблюдать это, запустите процесс, который генерирует данные и перенаправьте в файл с помощью > или >> (например, pv -L 10k /dev/urandom > blob). Пусть он запустится и измените размер файла (например, с помощью truncate). Вы увидите, что > сохраняет свое (растущее) смещение, а >> всегда добавляет к концу.

  • Если вы усекаете файл до меньшего размера (это может быть нулевой размер)
    • > не волнует, он напишет с нужным смещением, как будто ничего не произошло; сразу после того, как усечение смещения выходит за пределы конца файла, это приведет к тому, что файл восстановит свой старый размер и будет увеличиваться, пропущенные данные будут заполнены нулями (разреженным, если это возможно);
    • >> добавится к новому концу, файл вырастет из своего усеченного размера.
  • Если вы увеличите файл
    • > не волнует, он напишет с нужным смещением, как будто ничего не произошло; просто после изменения размера смещение находится где-то внутри файла, это приведет к тому, что файл на некоторое время перестанет расти, пока смещение не достигнет нового конца, а затем файл будет расти нормально;
    • >> добавится к новому концу, файл увеличится в увеличенном размере.

Другой пример - добавить (с отдельной >>) что-то дополнительное, когда запущен процесс генерации данных и записать в файл. Это похоже на увеличение файла.

  • Процесс генерации с > запишет с желаемым смещением и перезапишет дополнительные данные в конце концов.
  • Процесс генерации с >> пропустит новые данные и добавит их после (может возникнуть условие гонки, два потока могут чередоваться, но данные не должны быть перезаписаны).

пример

Имеет ли это значение на практике? Есть такой вопрос:

Я запускаю процесс, который выдает большой объем вывода на стандартный вывод. Отправка всего этого в файл [...] Могу ли я использовать какую-нибудь программу ротации журналов?

Этот ответ говорит, что решение - logrotate с опцией copytruncate которая действует следующим образом:

Усечение исходного файла журнала после создания копии вместо перемещения старого файла журнала и, при необходимости, создания нового.

Согласно тому, что я написал выше, перенаправление с помощью > сделает усеченный журнал большим в кратчайшие сроки. Разреженность спасет день, не нужно тратить значительное дисковое пространство. Тем не менее, в каждом последующем журнале будет все больше и больше ведущих нулей, которые совершенно не нужны.

Но если logrotate создает копии без сохранения разреженности, этим ведущим нулям потребуется все больше и больше дискового пространства при каждом создании копии. Я не исследовал поведение инструмента, оно может быть достаточно умным с разреженностью или сжатием на лету (если сжатие включено). Тем не менее, нули могут только создавать проблемы или быть в лучшем случае нейтральными; ничего хорошего в них нет.

В этом случае использование >> вместо > значительно лучше, даже если целевой файл еще не создан.


Спектакль

Как мы видим, два оператора действуют по-разному не только в начале, но и позже. Это может вызвать некоторые (тонкие?) разница в производительности На данный момент у меня нет значимых результатов тестирования, чтобы поддержать или опровергнуть его, но я думаю, что вы не должны автоматически предполагать, что их производительность в целом одинакова.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .