Найти тему
Блокнот математика

Рубрика "Секреты Вим". Как сохранить файл

В чем разница между буфером и файлом? Файл — это информация на запоминающем устройстве (на диске), доступная по имени. Буфер — это та же информация в оперативной памяти, доступная для чтения и изменения в Вим. Проще говоря, это копия файла (имеющегося или будущего), которую вы редактируете в Вим. Если вы открыли файл в Вим, то его содержимое скопировано в буфер. Изменения в буфере можно сохранить, в тот же или в другой файл. С буфером может быть связан файл (если вы открыли файл или сохранили буфер в него) или буфер может быть безымянным (если вы создали новый).

Их уже нет, но они - символ сохранения. По-английски каламбур есть: They died, but remain as the symbol of Saving
Их уже нет, но они - символ сохранения. По-английски каламбур есть: They died, but remain as the symbol of Saving

Сохранить буфер в связанный с ним файл позволит команда :write, или коротко :w.

Можно указать опции вида ++ff, ++enc, ++bin и ++nobin, позволяющие задать тип конца строки (не меняя опции ff), кодировку файла, а также выставить или сбросить флаг binary. Например:

:w ++enc=cp1251

Можно указать диапазон строк и тогда в файл запишется только он. По умолчанию диапазон 1,$ — весь файл.

Можно указать имя файла: тогда текст будет записан в него, но это копия, а буфер по-прежнему привязан к прежнему файлу (если буфер был безымянный, то теперь он связан с указанным файлом). Если файл уже существует, будет выдано предупреждение и запись не будет произведена. Но можно настоять, применив команду с восклицательным знаком: :w!

И это общее правило. Во всех командах, когда Вим может отказать из соображений безопасности, восклицательный знак означает "я настаиваю!"

Можно выставить флаг writeany, и тогда восклицательный знак подразумевается: Вим будет записывать всё, без предупреждения. Излишне пояснять, что это небезопасно, но вы можете пойти на это. если желаете. Не забываем про флаг confirm: если он выставлен, то Вим будет задавать вопросы.

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

Можно и передать файл внешней команде cmd: :w !cmd. Можно и диапазон указать. Отличие от :!cmd в том, что можно задать опции вида ++opt. Например, поменять кодировку.

Это бывает полезно при работе с кодировкой cp1251 (Windows). Иногда приходится. Внешние утилиты "видят" не текст, а черт-те что, и вот тогда перекодировка очень пригождается!

Можно использовать файл-устройство, вроде /dev/lpt0, хотя мне ни разу не приходилось записывать туда. Разве что в /dev/null. Читать из /dev/random приходилось... При записи в такой "файл" необходим восклицательный знак, так как файл уже "существует".

Может быть и так, что вы не хотите испортить файл, даже случайно. Защититься несложно: если флаг write сброшен (:set nowrite), то Вим вообще не может записывать файлы. Но временные файлы Вим записывать будет, если нужно.

А если выставлен флаг readonly, то данный буфер защищен от записи. Но его все равно можно записать, применив команду :w!. При этом флаг снимается, и потом можно записывать уже без проблем.

Флаг этот выставляется иногда автоматически. Например, если файл уже открыт в Вим (на сетевом диске или в другом окне), то Вим предложит выбор, в который входит и "открыть только для чтения". Сброс флага можно отключить, если в cpoptions добавить флаг Z. Тогда обойти readonly можно, но при следующей записи придется делать это снова.

И то, и другое может быть логично: иногда вы решили, что эта версия файла будет меняться, и хотите снять флаг (хотя это можно и вручную сделать), а порой вы хотите исправить что-то, но оставить файл защищенным от случайного изменения.

Если вы записываете весь буфер в тот файл, с которым он связан, то снимается признак "не сохранен" (флаг modified сброшен). Если буфер сохранен в другой файл, то обычно нет, файл считается "несохраненным": флаг modified выставлен. Но можно и это обойти, добавив в cpoptions флаг +.

Внимание! Это странно. Вы открыли файл: vim file
Изменили что-то. Выполнили команду :w file1
Если плюсик входит в cpoptions, то файл считается сохраненным, хотя файл file на диске не изменялся!

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

Если вы открыли новый буфер, не связанный ни с каким файлом, то :w выдаст ошибку, а :w file сделает то, что вы ожидаете: сохранит буфер в файл и свяжет его с ним.

Будьте очень внимательны, если запись не удалась! Не закрывайте Вим, пока не сохраните всё, что можно, читайте сообщения и не делайте резких движений.

Бывает, что вам надо сохранить копию файла и потом работать с ним, чтобы эта копия была связана с буфером. Для этого есть команда :saveas

Если не определен тип файла, он будет распознан. Флаг readonly будет сброшен. Можно указать опции вида ++opt и восклицательный знак для обхода запретов. Диапазон нельзя указывать: сохраняется всегда весь буфер. Что и логично.

Есть еще команда :wall (:wa), которая не относится ни к какой стене, а сохраняет все буферы в связанные с ними файлы. С восклицательным знаком преодолевает readonly и другие запреты (по возможности). Безымянные буферы не записываются (а куда?!).

При записи может создаваться резервная копия.

При записи нового файла выставляются права на чтение и запись файла (0666). Если в cpoptions есть флаг W, то Вим не будет записывать в защищенный от записи файл — имеются в виду системные права на запись. Если флага нет, то :w! попробует это сделать. Конечно, если прав у вас нет, то всё равно не получится. Но с админскими правами это может быть надо. С флагом W в cpoptions вы защитите свои файлы даже от самого себя!

Команда :wq делает всё то же, что и :w, но при успехе закрывает буфер. Вариант :xit (:x, :exit) тоже, но сохраняет только несохраненный буфер.

Подробно выход из Вим мы уже обсуждали.

Забавная тонкость. Команда :g иногда работает как разрывный диапазон строк, позволяя сделать что-то со строками, которые не обязательно идут подряд. Но для команд сохранения это не подходит! Потому что каждая строка проверяется и, если она подходит, на ней выполняется команда. Попытка выполнить :g/expr/w приведет не к сохранению подпадающих под выражение строк в файл, а к сохранению файла столько раз, сколько совпадений найдется. Можно так: :g/expr/.,.w! >> file. Вот это действительно запишет в файл только те строки, которые подходят.

Удачи, коллеги! God save you.

Научно-популярные каналы на Дзене: путеводитель
Новости популярной науки12 марта 2022