Question Comment fonctionne le vim "écrire avec sudo"?


Beaucoup d'entre vous ont probablement vu la commande qui vous permet d'écrire sur un fichier qui a besoin de l'autorisation root, même si vous avez oublié d'ouvrir vim avec sudo:

:w !sudo tee %

La chose est que je ne comprends pas ce qui se passe exactement ici.

Je l'ai déjà compris: w c'est pour ça

                                                        *: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 |:!|.

donc il passe toutes les lignes comme entrée standard.

le !sudo tee appels de partie tee avec des privilèges d'administrateur.

Pour que tout le monde ait du sens, le % devrait sortir le nom de fichier (en tant que paramètre pour tee), mais je ne trouve pas de références sur l'aide pour ce comportement.

tl; dr Quelqu'un pourrait-il m'aider à disséquer cette commande?


1148
2018-04-08 14:36


origine


Réponses:


% signifie "le fichier en cours"

Comme eugene y a souligné, % signifie en effet "le nom de fichier actuel". Une autre utilisation pour cela dans Vim est dans les commandes de substitution. Par exemple, :%s/foo/bar veux dire "dans le fichier actuel, remplacez les occurrences de foo avec bar. "Si vous mettez en évidence du texte avant de taper :s, vous verrez que les lignes en surbrillance prennent la place de % comme votre gamme de substitution.

:w ne met pas à jour votre fichier

Une partie confuse de cette astuce est que vous pourriez penser :w est en train de modifier votre fichier, mais ce n'est pas le cas. Si vous avez ouvert et modifié file1.txt, puis couru :w file2.txt, ce serait un "save as"; file1.txt ne serait pas modifié, mais le contenu actuel du tampon serait envoyé à file2.txt.

Au lieu de file2.txt, vous pouvez substituer une commande shell pour recevoir le contenu du tampon. Par exemple, :w !cat va juste afficher le contenu.

Si Vim n'a pas été exécuté avec sudo access, son :w ne peut pas modifier un fichier protégé, mais s'il transmet le contenu du tampon au shell, une commande dans la coquille pouvez être exécuté avec sudo. Dans ce cas, nous utilisons tee.

Té compris

Pour ce qui est de tee, image le tee commande comme un tuyau en forme de T dans une situation de tuyauterie bash normale: il dirige la sortie vers le (s) fichier (s) spécifié (s) et l'envoie également à la sortie standard, qui peut être capturé par la commande canalisée suivante.

Par exemple, dans ps -ax | tee processes.txt | grep 'foo', la liste des processus sera écrite dans un fichier texte et transmis le long de grep.

     +-----------+    tee     +------------+
     |           |  --------  |            |
     | ps -ax    |  --------  | grep 'foo' |
     |           |     ||     |            |
     +-----------+     ||     +------------+
                       ||   
               +---------------+
               |               |
               | processes.txt |
               |               |
               +---------------+

(Diagramme créé avec Asciiflow.)

Voir le tee page de manuel pour plus d'informations.

Tee comme un hack

Dans la situation décrite par votre question, en utilisant tee est un hack parce que nous ignorons la moitié de ce qu'il fait. sudo tee écrit dans notre fichier et envoie également le contenu du tampon à la sortie standard, mais nous ignorons la sortie standard. Nous n'avons pas besoin de passer quelque chose à une autre commande canalisée dans ce cas; nous utilisons juste tee comme une alternative d'écriture d'un fichier et que nous pouvons l'appeler avec sudo.

Faire ce tour facile

Vous pouvez ajouter ceci à votre .vimrc pour rendre cette astuce facile à utiliser: il suffit de taper :w!!.

" Allow saving of files as sudo when I forgot to start vim using sudo.
cmap w!! w !sudo tee > /dev/null %

le > /dev/nullpartie explicitement jette la sortie standard, puisque, comme je l'ai dit, nous n'avons pas besoin de passer quelque chose à une autre commande canalisée.


1272
2017-08-16 12:49



Dans la ligne de commande exécutée, % représente le nom de fichier actuel. Ceci est documenté dans :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.

Comme vous l'avez déjà découvert, :w !cmd canalise le contenu du tampon courant vers une autre commande. Quelle tee est une entrée standard de copie pour un ou plusieurs fichiers, et également pour la sortie standard. Donc, :w !sudo tee % > /dev/null écrit efficacement le contenu du tampon actuel dans le fichier en cours en étant racine. Une autre commande qui peut être utilisée pour cela est dd:

:w !sudo dd of=% > /dev/null

En tant que raccourci, vous pouvez ajouter ce mappage à votre .vimrc:

" Force saving files that require root permission 
cnoremap w!! w !sudo tee > /dev/null %

Avec ce qui précède, vous pouvez taper :w!!<Enter> pour enregistrer le fichier en tant que root.


88
2018-04-08 14:45



Cela fonctionne aussi bien:

:w !sudo sh -c "cat > %"

Ceci est inspiré par le commentaire de @Nathan Long.

REMARQUER:

" doit être utilisé au lieu de ' parce que nous voulons % être étendu avant de passer à la coquille.


18
2017-07-29 08:08



:w - Ecrire un fichier.

!sudo - Appelez la commande shell sudo.

tee - La sortie de la commande write (vim: w) redirigée en utilisant tee. Le% est rien, mais le nom du fichier en cours à savoir /etc/apache2/conf.d/mediawiki.conf. En d'autres termes, la commande tee est exécutée en tant que root et prend une entrée standard et l'écrit dans un fichier représenté par%. Cependant, cela vous demandera de recharger le fichier à nouveau (appuyez sur L pour charger les changements dans vim lui-même):

lien tutoriel


16
2018-06-04 06:02



La réponse acceptée couvre tout, alors je vais donner un autre exemple d'un raccourci que j'utilise, pour le compte rendu.

Ajoutez-le à votre etc/vim/vimrc (ou ~/.vimrc):

  • cnoremap w!! execute 'silent! write !sudo tee % >/dev/null' <bar> edit!

Où:

  • cnoremap: raconte vim que le raccourci suivant doit être associé dans la ligne de commande.
  • w!!: le raccourci lui-même.
  • execute '...': une commande qui exécute la chaîne suivante.
  • silent!: exécutez-le en silence
  • write !sudo tee % >/dev/null: la question OP, ajouté une redirection des messages à NULL faire une commande propre
  • <bar> edit!: cette astuce est la cerise du gâteau: elle appelle aussi le edit commande pour recharger le tampon et ensuite éviter les messages tels que le tampon a changé. <bar> est comment écrire le tuyau symbole pour séparer deux commandes ici.

J'espère que cela aide. Voir aussi pour d'autres problèmes:


3
2018-01-13 07:12



Je voudrais suggérer une autre approche de la "Oups j'ai oublié d'écrire sudo en ouvrant mon fichier " problème:

Au lieu de recevoir un permission deniedet avoir à taper :w!!, Je trouve plus élégant d'avoir un conditionnel vim commande qui fait sudo vim si le propriétaire du fichier est root.

Ceci est aussi facile à mettre en œuvre (il pourrait même être mises en œuvre plus élégantes, je ne suis évidemment pas un gourou bash):

function vim(){
  OWNER=$(stat -c '%U' $1)
  if [[ "$OWNER" == "root" ]]; then
    sudo /usr/bin/vim $*;
  else
    /usr/bin/vim $*;
  fi
}

Et ça marche vraiment bien.

C'est plus bashapproche centrée sur un vim-un pour tout le monde ne pourrait pas l'aimer.

Bien sûr:

  • il y a des cas d'utilisation où il échouera (quand le propriétaire du fichier n'est pas root mais nécessite sudo, mais la fonction peut être éditée quand même)
  • cela n'a pas de sens en utilisant vim pour lire seulement un fichier (en ce qui me concerne, j'utilise tail ou cat pour les petits fichiers)

Mais je trouve que cela apporte beaucoup mieux expérience utilisateur dev, qui est quelque chose que mon humble avis tend à être oublié lors de l'utilisation bash. :-)


1
2018-02-28 18:21