Avvertenze comuni
Il metodo più comune per aggirare il problema del file di sola lettura è aprire una pipe al file corrente come superutente utilizzando un'implementazione di sudo tee
. Tuttavia, tutte le soluzioni più popolari che ho trovato su Internet hanno una combinazione di diversi potenziali avvertimenti:
- L'intero file viene scritto sul terminale, così come il file. Questo può essere lento per file di grandi dimensioni, specialmente su connessioni di rete lente.
- Il file perde le sue modalità e attributi simili.
- I percorsi dei file con caratteri o spazi insoliti potrebbero non essere gestiti correttamente.
soluzioni
Per aggirare tutti questi problemi, è possibile utilizzare il seguente comando:
" On POSIX (Linux/Mac/BSD):
:silent execute 'write !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'
" Depending on the implementation, you might need this on Windows:
:silent execute 'write !sudo tee ' . shellescape(@%, 1) . ' >NUL'
Questi possono essere abbreviati, rispettosamente:
:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'
:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >NUL'
Spiegazione
:
inizia il comando; dovrai digitare questo carattere in modalità normale per iniziare a inserire un comando. Dovrebbe essere omesso negli script.
sil[ent]
sopprime l'output dal comando. In questo caso, vogliamo interrompere il Press any key to continue
prompt simile a quello che appare dopo aver eseguito il :!
comando.
exec[ute]
esegue una stringa come comando. Non possiamo semplicemente eseguire :write
perché non elaborerà la chiamata di funzione necessaria.
!
rappresenta il :!
comando: l'unico comando che :write
accetta. Normalmente, :write
accetta un percorso di file in cui scrivere. :!
da solo esegue un comando in una shell (ad esempio, usando bash -c
). Con :write
, eseguirà il comando nella shell e quindi scriverà l'intero file stdin
.
sudo
dovrebbe essere ovvio, poiché è per questo che sei qui. Esegui il comando come superutente. Ci sono molte informazioni in rete su come funziona.
tee
pipe stdin
al file specificato. :write
scriverà su stdin
, quindi il superutente tee
riceverà il contenuto del file e scriverà il file. Non creerà un nuovo file - basta sovrascrivere il contenuto - quindi le modalità e gli attributi del file verranno preservati.
shellescape()
sfugge ai caratteri speciali nel percorso del file indicato come appropriato per la shell corrente. Con un solo parametro, in genere racchiuderebbe il percorso tra virgolette, se necessario. Dato che stiamo inviando a una riga di comando della shell completa, vorremmo passare un valore diverso da zero come secondo argomento per consentire l'escape di backslash di altri caratteri speciali che potrebbero altrimenti inciampare nella shell.
@%
legge il contenuto del %
registro, che contiene il nome del file del buffer corrente. Non è necessariamente un percorso assoluto, quindi assicurati di non aver modificato la directory corrente. In alcune soluzioni vedrai omesso il simbolo commerciale. A seconda della posizione, %
è un'espressione valida e ha lo stesso effetto della lettura del %
registro. Nidificato all'interno di un'altra espressione, in genere il collegamento non è consentito: come in questo caso.
>NUL
e >/dev/null
reindirizzare stdout
al dispositivo null della piattaforma. Anche se abbiamo messo a tacere il comando, non vogliamo che tutte le spese generali associate al piping stdin
tornino a VIM - è meglio scaricarlo il prima possibile. NUL
è il dispositivo null su DOS, MS-DOS e Windows, non è un file valido. A partire dal reindirizzamento di Windows 8 su NUL non risulta che un file chiamato NUL venga scritto. Prova a creare un file sul desktop chiamato NUL, con o senza estensione: non sarai in grado di farlo. (Ci sono molti altri nomi di dispositivi in Windows che potrebbero valere la pena di conoscere.)
~ / .Vimrc
Platform-Dependent
Naturalmente, non vuoi ancora memorizzarli e digitarli ogni volta. È molto più facile associare il comando appropriato a un comando utente più semplice. Per fare ciò su POSIX, puoi aggiungere la seguente riga al tuo ~/.vimrc
file, creandolo se non esiste già:
command W silent execute 'write !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'
Ciò ti consentirà di digitare il comando: W (sensibile al maiuscolo / minuscolo) per scrivere il file corrente con autorizzazioni di superutente - molto più semplice.
Piattaforma indipendente
Uso un ~/.vimrc
file indipendente dalla piattaforma che si sincronizza tra i computer, quindi ho aggiunto la mia funzionalità multipiattaforma al mio. Ecco un ~/.vimrc
con solo le impostazioni pertinenti:
#!vim
" Use za (not a command; the keys) in normal mode to toggle a fold.
" META_COMMENT Modeline Definition: {{{1
" vim: ts=4 sw=4 sr sts=4 fdm=marker ff=unix fenc=utf-8
" ts: Actual tab character stops.
" sw: Indentation commands shift by this much.
" sr: Round existing indentation when using shift commands.
" sts: Virtual tab stops while using tab key.
" fdm: Folds are manually defined in file syntax.
" ff: Line endings should always be <NL> (line feed #09).
" fenc: Should always be UTF-8; #! must be first bytes, so no BOM.
" General Commands: User Ex commands. {{{1
command W call WriteAsSuperUser(@%) " Write file as super-user.
" Helper Functions: Used by user Ex commands. {{{1
function GetNullDevice() " Gets the path to the null device. {{{2
if filewritable('/dev/null')
return '/dev/null'
else
return 'NUL'
endif
endfunction
function WriteAsSuperUser(file) " Write buffer to a:file as the super user (on POSIX, root). {{{2
exec '%write !sudo tee ' . shellescape(a:file, 1) . ' >' . GetNullDevice()
endfunction
" }}}1
" EOF