จะบันทึกไฟล์ที่ฉันไม่มีสิทธิ์เขียนได้อย่างไร?


26

บางครั้งมันเกิดขึ้นที่ฉันเปิดไฟล์และทำการปรับเปลี่ยนบางอย่างในฐานะผู้ใช้ของฉันเองโดยไม่สังเกตเห็นหรือ "ลืม" เพื่อสังเกต[read-only]คำเตือนในบรรทัดสถานะ (เช่น/etcไฟล์ config แบบสุ่มบางอย่าง/etc/resolv.conf)

:w!เห็นได้ชัดว่าล้มเหลวในกรณีนี้เนื่องจากผู้ใช้ของฉันไม่มีสิทธิ์ในการเขียนอยู่แล้ว ดังนั้นฉันต้อง:w /home/filenameออกและsudo mv ...อึดอัดมาก

มีวิธีใดบ้างที่ฉันเลื่อนระดับชั่วคราวไปที่รูทเพื่อให้สามารถบันทึกไฟล์ที่เปิดในปัจจุบันได้ (ฉันอยู่ในsudoersหรือ / และฉันสามารถsuโดยตรง)?

คำตอบ:


24

เคล็ดลับคือการใช้การโทรภายนอกไปที่sudo:

:w !sudo tee %

มันทำงานอย่างไร:

  • :w !<command>ดำเนินการ<command>กับเนื้อหาของบัฟเฟอร์เป็น stdin
  • teeทำซ้ำ stdin ไปยังไฟล์ & stdout; %ขยายไปยังชื่อไฟล์ปัจจุบัน ..
  • คุณนำหน้าสิ่งนี้พร้อมกับsudoสิทธิ์การรูท

คุณไม่ได้บันทึกไฟล์ด้วย Vim จริงๆคุณกำลังเรียกโปรแกรมภายนอกเพื่อเขียนทับเนื้อหาของไฟล์ที่คุณกำลังแก้ไข นี่คือเหตุผลที่คุณจะได้รับคำเตือนจาก Vim:

W12: Warning: File "xxx" has changed and the buffer was changed in Vim as well
See ":help W12" for more info.
[O]K, (L)oad File: 

คุณสามารถเปลี่ยนให้เป็นฟังก์ชัน:

fun! SuperWrite()
        write !sudo tee %
        " Or with :silent (but that doesn't seem to work for everyone)
        "silent write !sudo tee %
        edit!
endfun

และปุ่มลัด:

nnoremap <Leader>w! :call SuperWrite()<CR>

ด้วยsuผู้ใช้ root เท่านั้นที่สามารถใช้-cเพื่อเรียกใช้งานคำสั่งได้ทันที ฉันไม่คิดว่าคุณสามารถใช้suในการทำเช่นนี้ แต่อาจมีเคล็ดลับที่ฉันไม่รู้ ...


SuperWriteใช้งานได้ แต่มันสะท้อนไฟล์กลับมาที่คุณ เล่นมัน:silentเหมือนมีคุณป้อนรหัสผ่านของคุณลูกหูลูกตา
TankorSmash

@TankorSmash ขอบคุณ; คำตอบที่อัปเดต ไม่แน่ใจว่าคุณหมายถึงอะไรด้วย "ป้อนรหัสผ่านของคุณอย่างล่องหน"? silentดูเหมือนว่าการเพิ่มจะทำงานได้ดีใช่ไหม
Martin Tournoij

ฉันไม่ได้เรียกใช้ vim ด้วย sudo เพื่อที่อาจจะเล่นที่นี่ แต่เมื่อฉันไปที่ sudo ทีไฟล์มันจะแจ้งให้ฉันสำหรับรหัสผ่าน sudo ถ้าเงียบฉันไม่เห็นข้อความแจ้ง แต่ยังต้องป้อนรหัสผ่าน
TankorSmash

1
สิ่งที่คุณเห็นคือฟังก์ชั่นมาตรฐานของ echoing to stdout และไฟล์ที่กำหนด วิธีแก้ปัญหาคือเปลี่ยนเส้นทาง stdout ไปที่ / dev / null a: w ! tee % > /dev/null สิ่งนี้จะยังคงสะท้อนผลลัพธ์ของคำสั่ง (บรรทัดเดียว) แต่ไม่รวมเนื้อหาบัฟเฟอร์ทั้งหมด
Jon Carter

แทนที่จะใช้teeแล้วทิ้งผลลัพธ์มันจะไม่catทำงานถ้าคุณไม่ต้องการพิมพ์ไฟล์?
Lie Ryan

12

ฉันใช้การแมปต่อไปนี้ใน. vimrc ซึ่งฉันพบว่ามีประโยชน์:

cnoremap w!! w !sudo tee %

ง่ายต่อการจดจำเพราะwเป็น "เขียน" w!คือ "กำลังเขียน" และw!!"เขียน super-duper-force" : P


1
ฉันได้ทำแผนที่มานานWแล้ว แต่w!!มีเหตุผลมากกว่านี้จะอัปเดต. vimrc ของฉัน ขอบคุณ
jalanb
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.