Как работает трюк vim "писать с sudo"?
многие из вас, вероятно, видели команду, которая позволяет писать на файл, который нуждается в разрешении root, даже если вы забыли открыть vim с sudo:
:w !sudo tee %
дело в том, что я не понимаю, что именно здесь происходит.
Я уже понял это:
w
для этого
*:w_c* *:write_c*
:[range]w[rite] [++opt] !{cmd}
Execute {cmd} with [range] lines as standard input
(note the space in front of the '!'). {cmd} is
executed like with ":!{cmd}", any '!' is replaced with
the previous command |:!|.
таким образом, он передает все строки в качестве стандартного ввода.
на !sudo tee
часть звонки tee
С правами администратора.
для всех чтобы иметь смысл,%
выводит имя файла (в качестве параметра tee
), но я не могу найти ссылки на помощь такого поведения.
tl; dr может кто-нибудь помочь мне разобрать эту команду?
6 ответов
на :w !sudo tee %
...
%
означает "текущий файл"
As Евгений Игоревич указал, %
действительно означает "текущее имя файла". Другое использование для этого в Vim-в командах подстановки. Например, :%s/foo/bar
значит "в текущем файле заменить вхождения foo
С bar
."Если вы выделите текст перед вводом :s
, вы увидите, что выделенные строки занимают место %
как ваше диапазон замещения.
:w
не обновляет файл
одна запутанная часть этого трюка заключается в том, что вы можете подумать :w
изменяет ваш файл, но это не так. Если вы открыли и изменили file1.txt
, затем побежал :w file2.txt
, это было бы "сохранить как";file1.txt
не будет изменен, но текущее содержимое буфера будет отправлено file2.txt
.
вместо file2.txt
вы можете замените команду оболочки для получения буфера содержание. Например, :w !cat
будет просто отображать содержание.
если Vim не был запущен с доступом sudo, его :w
не удается изменить защищенный файл, но если он передает содержимое буфера в оболочку, команда в оболочке can работать с sudo. В этом случае, мы используем tee
.
понимание tee
как tee
, картина tee
команда как Т-образная труба в нормальной ситуации трубопровода Баш: он направляет вывод в указанный файл(Ы) и также отправляет его на стандартный вывод, который может быть захвачен следующей командой piped.
например,ps -ax | tee processes.txt | grep 'foo'
, список процессов будет записан в текстовый файл и до grep
.
+-----------+ tee +------------+
| | -------- | |
| ps -ax | -------- | grep 'foo' |
| | || | |
+-----------+ || +------------+
||
+---------------+
| |
| processes.txt |
| |
+---------------+
(диаграмма создана с помощью Asciiflow.)
посмотреть tee
man page для получения дополнительной информации.
тройник как hack
в ситуации, которую описывает ваш вопрос,используя tee
это хак, потому что мы игнорируем половину того, что он делает. sudo tee
запись в наш файл и отправляет содержимое буфера на стандартный вывод, но мы игнорируем стандартный вывод. В этом случае нам не нужно ничего передавать другой команде piped; мы просто используем tee
как альтернативный способ записи в файл и так, что мы можем назвать его sudo
.
сделать это трюк легкий
вы можете добавить это в ваш .vimrc
чтобы сделать этот трюк легкий в использовании: просто введите :w!!
.
" Allow saving of files as sudo when I forgot to start vim using sudo.
cmap w!! w !sudo tee > /dev/null %
на > /dev/null
часть явно выбрасывает стандартный вывод, так как, как я сказал, нам не нужно ничего передавать другой команде piped.
в выполненной командной строке %
стоит нынешнее имя файла. Это задокументировано в :help cmdline-special
:
In Ex commands, at places where a file name can be used, the following
characters have a special meaning.
% Is replaced with the current file name.
как вы уже выяснили, :w !cmd
передает содержимое текущего буфера другой команде. Что?!--18-->tee
does копирует стандартный ввод в один или несколько файлов, а также в стандартный вывод. Следовательно,:w !sudo tee % > /dev/null
эффективно записывает содержимое буфера в текущий файл будучи root. Другая команда, которая может быть использована для этого, -dd
:
:w !sudo dd of=% > /dev/null
в качестве ярлыка вы можете добавить это сопоставление в свой .vimrc
:
" Force saving files that require root permission
cnoremap w!! w !sudo tee > /dev/null %
с вышеизложенным вы можете ввести :w!!<Enter>
сохранить файл как root.
Это также работает хорошо:
:w !sudo sh -c "cat > %"
это вдохновлено комментарием @Nathan Long.
обратите внимание:
"
должен использоваться вместо '
потому что мы хотим %
будет расширен до раковины.
:w
- записать файл.
!sudo
- вызовите команду shell sudo.
tee
- вывод команды write (vim :w) перенаправляется с помощью tee. % - Это не что иное, как текущее имя файла, т. е. /etc/apache2/conf.д/медиавики.conf. Другими словами, команда tee запускается как root и принимает стандартный ввод и записывает его в файл, представленный %. Тем не менее, это предложит перезагрузить файл снова (нажмите L, чтобы загрузить изменения в самом vim):
принятый ответ охватывает все это, поэтому я просто приведу еще один пример ярлык это я использую для записи.
добавить его в свой etc/vim/vimrc
(или ~/.vimrc
):
cnoremap w!! execute 'silent! write !sudo tee % >/dev/null' <bar> edit!
где:
-
cnoremap
: говорит vim что следующий ярлык должен быть связан в командной строке. -
w!!
: сам ярлык. -
execute '...'
: команда которые выполняют следующую строку. -
silent!
: запустить его молча -
write !sudo tee % >/dev/null
: вопрос OP, добавлено перенаправление сообщений наNULL
сделать "чистую" команду -
<bar> edit!
: этот трюк является вишней торта: он также называетedit
команда для перезагрузки буфера, а затем избежать сообщений, таких как буфер изменился.<bar>
как писать труба символ для разделения двух команд здесь.
надеюсь, что это помогает. См. также для других проблем:
я хотел бы предложить другой подход к "Ой, я забыл написать sudo
при открытии моего файла" вопрос:
вместо permission denied
, и имея типа :w!!
, Я считаю более элегантным иметь условное