Peringatan umum
Metode yang paling umum untuk mengatasi masalah file read-only adalah membuka pipa ke file saat ini sebagai pengguna super menggunakan implementasi sudo tee
. Namun, semua solusi paling populer yang saya temukan di Internet memiliki kombinasi beberapa peringatan potensial:
- Seluruh file ditulis ke terminal, serta file. Ini bisa lambat untuk file besar, terutama melalui koneksi jaringan yang lambat.
- File kehilangan mode dan atribut serupa.
- Jalur file dengan karakter atau spasi yang tidak biasa mungkin tidak ditangani dengan benar.
Solusi
Untuk mengatasi semua masalah ini, Anda dapat menggunakan perintah berikut:
" 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'
Ini dapat disingkat, dengan hormat:
:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'
:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >NUL'
Penjelasan
:
memulai perintah; Anda harus mengetikkan karakter ini dalam mode normal untuk mulai memasukkan perintah. Itu harus dihilangkan dalam skrip.
sil[ent]
menekan output dari perintah. Dalam hal ini, kami ingin menghentikan Press any key to continue
prompt-like yang muncul setelah menjalankan :!
perintah.
exec[ute]
mengeksekusi string sebagai perintah. Kami tidak bisa hanya menjalankannya :write
karena itu tidak akan memproses pemanggilan fungsi yang diperlukan.
!
mewakili :!
perintah: satu-satunya perintah yang :write
menerima. Biasanya, :write
menerima jalur file yang akan ditulis. :!
dengan sendirinya menjalankan perintah di shell (misalnya, menggunakan bash -c
). Dengan :write
, itu akan menjalankan perintah di shell, dan kemudian menulis seluruh file stdin
.
sudo
harus jelas, karena itu kau ada di sini. Jalankan perintah sebagai pengguna super. Ada banyak informasi di internet tentang cara kerjanya.
tee
pipa stdin
ke file yang diberikan. :write
akan menulis ke stdin
, maka pengguna super tee
akan menerima konten file dan menulis file. Itu tidak akan membuat file baru - cukup timpa isinya - sehingga mode dan atribut file akan dipertahankan.
shellescape()
lolos karakter khusus di jalur file yang diberikan sesuai untuk shell saat ini. Dengan hanya satu parameter, biasanya hanya menyertakan path dalam tanda kutip yang diperlukan. Karena kami mengirim ke baris perintah shell penuh, kami ingin memberikan nilai bukan nol sebagai argumen kedua untuk mengaktifkan backslash-escape dari karakter khusus lain yang mungkin menjebak shell.
@%
membaca isi %
register, yang berisi nama file buffer saat ini. Itu belum tentu jalur absolut, jadi pastikan Anda belum mengubah direktori saat ini. Dalam beberapa solusi, Anda akan melihat simbol komersial saat dihilangkan. Bergantung pada lokasi, %
adalah ekspresi yang valid, dan memiliki efek yang sama dengan membaca %
register. Bersarang di dalam ungkapan lain pintasan umumnya tidak diizinkan: seperti dalam kasus ini.
>NUL
dan >/dev/null
redirect stdout
ke perangkat nol platform. Meskipun kami telah membungkam perintah, kami tidak ingin semua overhead terkait dengan pemipaan stdin
kembali ke vim - terbaik untuk membuangnya sedini mungkin. NUL
adalah perangkat nol pada DOS, MS-DOS, dan Windows, bukan file yang valid. Pada pengalihan Windows 8 ke NUL tidak menghasilkan file bernama NUL sedang ditulis. Coba buat file di desktop Anda bernama NUL, dengan atau tanpa ekstensi file: Anda tidak akan bisa melakukannya. (Ada beberapa nama perangkat lain di Windows yang mungkin perlu Anda ketahui.)
~ / .vimrc
Platform-Ketergantungan
Tentu saja, Anda masih tidak ingin mengingatnya dan mengetiknya setiap kali. Jauh lebih mudah untuk memetakan perintah yang sesuai ke perintah pengguna yang lebih sederhana. Untuk melakukan ini pada POSIX, Anda bisa menambahkan baris berikut ke ~/.vimrc
file Anda , membuatnya jika belum ada:
command W silent execute 'write !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'
Ini akan memungkinkan Anda untuk mengetik perintah: W (peka huruf besar kecil) untuk menulis file saat ini dengan izin pengguna super - jauh lebih mudah.
Platform-Independen
Saya menggunakan file platform-independen ~/.vimrc
yang menyinkronkan di seluruh komputer, jadi saya menambahkan fungsionalitas multi-platform untuk menambang. Berikut ini ~/.vimrc
dengan hanya pengaturan yang relevan:
#!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