婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > Linux環境下VI/VIM編輯文件時無權限保存的解決方法(普通用戶)

Linux環境下VI/VIM編輯文件時無權限保存的解決方法(普通用戶)

熱門標簽:地圖標注行業發展如何 中山ai電銷機器人招商 河南400電話如何辦理 寧波電信400電話辦理 電銷機器人賺錢思路 太原地圖標注推廣員 怎么坐地圖標注 疏附縣地圖標注 河南營銷智能外呼系統價格多少

在Linux環境下,如果直接使用VI/VIM命令編輯沒有修改權限的文件時,保存的時候就會提示用戶無法進行保存操作,一般的解決方法只能是關閉文件重新以sudo權限打開該文件編輯后再保存(前提是用戶具有sudo權限)。其實,在VI/VIM模式下通過一些簡單的命令,就能在不關閉當前文件的情況下達到保存文件的目的。

方法一

關于%! sudo tee % > /dev/null這條命令的說明如下

此命令是把當前文件(即%)作為stdin傳給sudo tee命令來執行。

方法二
 

在Linux上工作的朋友很可能遇到過這樣一種情況,當你用Vim編輯完一個文件時,運行:wq保存退出,突然蹦出一個錯誤:

E45: 'readonly' option is set (add ! to override)

這表明文件是只讀的,按照提示,加上!強制保存::w!,結果又一個錯誤出現:

"readonly-file-name" E212: Can't open file for writing

文件明明存在,為何提示無法打開?這錯誤又代表什么呢?查看文檔:help E212:

For some reason the file you are writing to cannot be created or overwritten.
The reason could be that you do not have permission to write in the directory
or the file name is not valid.

原來是可能沒有權限造成的。此時你才想起,這個文件需要root權限才能編輯,而當前登陸的只是普通用戶,在編輯之前你忘了使用sudo來啟動Vim,所以才保存失敗。于是為了防止修改丟失,你只好先把它保存為另外一個臨時文件temp-file-name,然后退出Vim,再運行sudo mv temp-file-name readonly-file-name覆蓋原文件。

但這樣操作過于繁瑣。而且如果只是想暫存此文件,還需要接著修改,則希望保留Vim的工作狀態,比如編輯歷史,buffer狀態等等,該怎么辦?能不能在不退出Vim的情況下獲得root權限來保存這個文件?

解決方案

答案是可以,執行這樣一條命令即可:

:w !sudo tee %

接下來我們來分析這個命令為什么可以工作。首先查看文檔:help :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 |:!|.

The default [range] for the ":w" command is the whole buffer (1,$)

把這個使用方法對應前面的命令,如下所示:

:       w               !sudo tee %
|       |               |  |
:[range]w[rite] [++opt] !{cmd}

我們并未指定range,參見幫助文檔最下面一行,當range未指定時,默認情況下是整個文件。此外,這里也沒有指定opt。

Vim中執行外部命令

接下來是一個嘆號!,它表示其后面部分是外部命令,即sudo tee %。文檔中說的很清楚,這和直接執行:!{cmd}是一樣的效果。后者的作用是打開shell執行一個命令,比如,運行:!ls,會顯示當前工作目錄下的所有文件,這非常有用,任何可以在shell中執行的命令都可以在不退出Vim的情況下運行,并且可以將結果讀入到Vim中來。試想,如果你要在Vim中插入當前工作路徑或者當前工作路徑下的所有文件名,你可以運行:

:r !pwd或:r !ls

此時所有的內容便被讀入至Vim,而不需要退出Vim,執行命令,然后拷貝粘貼至Vim中。有了它,Vim可以自由的操作shell而無需退出。

命令的另一種表示形式

再看前面的文檔:

Execute {cmd} with [range] lines as standard input

所以實際上這個:w并未真的保存當前文件,就像執行:w new-file-name時,它將當前文件的內容保存到另外一個new-file-name的文件中,在這里它相當于一個另存為,而不是保存。它將當前文檔的內容寫到后面cmd的標準輸入中,再來執行cmd,所以整個命令可以轉換為一個具有相同功能的普通shell命令:

$ cat readonly-file-name | sudo tee %

這樣看起來”正常”些了。其中sudo很好理解,意為切換至root執行后面的命令,tee和%是什么呢?

%的意義

我們先來看%,執行:help cmdline-special可以看到:

In Ex commands, at places where a file name can be used, the following
characters have a special meaning. These can also be used in the expression
function expand() |expand()|.
% Is replaced with the current file name. *:_%* *c_%*

在執行外部命令時,%會擴展成當前文件名,所以上述的cmd也就成了sudo tee readonly-file-name。此時整個命令即:

$ cat readonly-file-name | sudo tee readonly-file-name

注意:在另外一個地方我們也經常用到%,沒錯,替換。但是那里%的作用不一樣,執行:help :%查看文檔:

Line numbers may be specified with: *:range* *E14* *{address}*
{number} an absolute line number
...
% equal to 1,$ (the entire file) *:%*

在替換中,%的意義是代表整個文件,而不是文件名。所以對于命令:%s/old/new/g,它表示的是替換整篇文檔中的old為new,而不是把文件名中的old換成new。

tee的作用

現在只剩一個難點: tee。它究竟有何用?維基百科上對其有一個詳細的解釋,你也可以查看man page。下面這幅圖很形象的展示了tee是如何工作的:

ls -l的輸出經過管道傳給了tee,后者做了兩件事,首先拷貝一份數據到文件file.txt,同時再拷貝一份到其標準輸出。數據再次經過管道傳給less的標準輸入,所以它在不影響原有管道的基礎上對數據作了一份拷貝并保存到文件中。看上圖中間部分,它很像大寫的字母T,給數據流動增加了一個分支,tee的名字也由此而來。

現在上面的命令就容易理解了,tee將其標準輸入中的內容寫到了readonly-file-name中,從而達到了更新只讀文件的目的。當然這里其實還有另外一半數據:tee的標準輸出,但因為后面沒有跟其它的命令,所以這份輸出相當于被拋棄。當然也可以在后面補上> /dev/null,以顯式的丟棄標準輸出,但是這對整個操作沒有影響,而且會增加輸入的字符數,因此只需上述命令即可。

命令執行之后

運行完上述命令后,會出現下面的提示:

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

Vim提示文件更新,詢問是確認還是重新加載文件。建議直接輸入O,因為這樣可以保留Vim的工作狀態,比如編輯歷史,buffer等,撤消等操作仍然可以繼續。而如果選擇L,文件會以全新的文件打開,所有的工作狀態便丟失了,此時無法執行撤消,buffer中的內容也被清空。

更簡單的方案:映射

上述方式非常完美的解決了文章開始提出的問題,但畢竟命令還是有些長,為了避免每次輸入一長串的命令,可以將它映射為一個簡單的命令加到.vimrc中:

" Allow saving of files as sudo when I forgot to start vim using sudo.

cmap w!! w !sudo tee > /dev/null %

這樣,簡單的運行:w!!即可。命令后半部分> /dev/null在前面已經解釋過,作用為顯式的丟掉標準輸出的內容。

另一種思路

至此,一個比較完美但很tricky的方案已經完成。你可能會問,為什么不用下面這樣更常見的命令呢?這不是更容易理解,更簡單一些么?

:w !sudo cat > %

重定向的問題

我們來分析一遍,像前面一樣,它可以被轉換為相同功能的shell命令:

$ cat readonly-file-name | sudo cat > %

這條命令看起來一點問題沒有,可一旦運行,又會出現另外一個錯誤:

/bin/sh: readonly-file-name: Permission denied

shell returned 1

這是怎么回事?不是明明加了sudo么,為什么還提示說沒有權限?稍安勿躁,原因在于重定向,它是由shell執行的,在一切命令開始之前,shell便會執行重定向操作,所以重定向并未受sudo影響,而當前的shell本身也是以普通用戶身份啟動,也沒有權限寫此文件,因此便有了上面的錯誤。

重定向方案

這里介紹了幾種解決重定向無權限錯誤的方法,當然除了tee方案以外,還有一種比較方便的方案:以sudo打開一個shell,然后在該具有root權限的shell中執行含重定向的命令,如:

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

可是這樣執行時,由于單引號的存在,所以在Vim中%并不會展開,它被原封不動的傳給了shell,而在shell中,一個單獨的%相當于nil,所以文件被重定向到了nil,所有內容丟失,保存文件失敗。

既然是由于%沒有展開導致的錯誤,那么試著將單引號'換成雙引號"再試一次:

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

成功!這是因為在將命令傳到shell去之前,%已經被擴展為當前的文件名。有關單引號和雙引號的區別可以參考這里,簡單的說就是單引號會將其內部的內容原封不動的傳給命令,但是雙引號會展開一些內容,比如變量,轉義字符等。

當然,也可以像前面一樣將它映射為一個簡單的命令并添加到.vimrc中:

" Allow saving of files as sudo when I forgot to start vim using sudo.

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

注意:這里不再需要把輸出重定向到/dev/null中。

寫在結尾

至此,借助Vim強大的靈活性,實現了兩種方案,可以在以普通用戶啟動的Vim中保存需root權限的文件。兩者的原理類似,都是利用了Vim可以執行外部命令這一特性,區別在于使用不同的shell命令。如果你還有其它的方案,歡迎給我留言。

(全文完)

feihu

2014.07.30 于 Shenzhen

標簽:滄州 榆林 山南 淘寶邀評 保定 樂山 河北 河池

巨人網絡通訊聲明:本文標題《Linux環境下VI/VIM編輯文件時無權限保存的解決方法(普通用戶)》,本文關鍵詞  Linux,環境,下,VIM,編輯,文件,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Linux環境下VI/VIM編輯文件時無權限保存的解決方法(普通用戶)》相關的同類信息!
  • 本頁收集關于Linux環境下VI/VIM編輯文件時無權限保存的解決方法(普通用戶)的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    首页国产丝袜综合| 日韩欧美你懂的| 国产精品自拍毛片| 玖玖九九国产精品| 日韩综合一区二区| 日韩vs国产vs欧美| 九一九一国产精品| 国产一区二区看久久| 丁香婷婷深情五月亚洲| 国产成人在线免费观看| 国产老肥熟一区二区三区| 国产成人在线观看免费网站| 成人美女视频在线看| 色婷婷久久久综合中文字幕| 欧美在线高清视频| 日韩欧美一级二级三级| 欧美v亚洲v综合ⅴ国产v| 久久一夜天堂av一区二区三区| 久久人人爽爽爽人久久久| 久久综合狠狠综合| 成人免费在线观看入口| 午夜精品视频一区| 九一九一国产精品| 91免费国产视频网站| 欧美综合色免费| 2欧美一区二区三区在线观看视频 337p粉嫩大胆噜噜噜噜噜91av | 韩国女主播一区二区三区| 美女高潮久久久| 丁香激情综合五月| 精品1区2区3区| 欧美精品一区二区三| 中文字幕中文字幕在线一区| 亚洲午夜在线电影| 国产黄色精品网站| 777亚洲妇女| 欧美激情艳妇裸体舞| 日韩影视精彩在线| 国产乱妇无码大片在线观看| 欧亚洲嫩模精品一区三区| 久久一区二区三区四区| 亚洲一区二区三区影院| 极品少妇xxxx偷拍精品少妇| 一本到高清视频免费精品| 日韩三级伦理片妻子的秘密按摩| 中文字幕亚洲精品在线观看| 精品一区二区三区免费视频| 在线观看日韩一区| 国产精品久久一级| 紧缚捆绑精品一区二区| 欧美精品三级在线观看| 国产精品国产三级国产有无不卡| 青青草原综合久久大伊人精品优势| 91伊人久久大香线蕉| 欧美一区二区三区的| 一区二区三区蜜桃| 99热精品一区二区| 久久久久久久久久电影| 免费在线观看一区| 日韩一级片在线播放| 亚洲国产精品欧美一二99| 不卡一区在线观看| 国产欧美精品国产国产专区| 精品在线你懂的| 91精品国产色综合久久不卡蜜臀 | 欧美久久一区二区| 亚洲欧美自拍偷拍色图| 国产成人av资源| 久久久青草青青国产亚洲免观| 美女国产一区二区三区| 日韩一区二区三区在线视频| 亚洲一区二区三区三| 色综合婷婷久久| 亚洲欧美激情在线| 91在线观看视频| 亚洲人成网站色在线观看| 99这里只有精品| 国产精品不卡一区二区三区| 成人午夜视频福利| 亚洲日本欧美天堂| 欧美三级一区二区| 性感美女久久精品| 日韩欧美国产1| 狠狠色丁香婷婷综合久久片| 久久综合九色综合欧美亚洲| 成人久久视频在线观看| 亚洲乱码国产乱码精品精的特点| 色婷婷av久久久久久久| 亚洲资源在线观看| 538在线一区二区精品国产| 精品在线一区二区| 国产精品久久久久久久久免费丝袜 | 免费成人在线视频观看| 欧美精品一区二区三区在线| 韩国成人精品a∨在线观看| 欧美极品另类videosde| 91污片在线观看| 亚洲不卡一区二区三区| 精品成人a区在线观看| 国产老妇另类xxxxx| 一区二区三区**美女毛片| 日韩精品专区在线影院重磅| 国产伦精品一区二区三区视频青涩 | 日韩精品一区二区三区在线| 丰满少妇在线播放bd日韩电影| 国产精品不卡在线观看| 在线不卡中文字幕播放| 国产精品一区二区不卡| 亚洲综合无码一区二区| 欧美tk—视频vk| 99久久精品费精品国产一区二区| 亚洲bt欧美bt精品| 中文字幕乱码久久午夜不卡| 欧美三级视频在线播放| 成人永久看片免费视频天堂| 亚洲风情在线资源站| 国产视频一区二区在线| 欧美另类久久久品| 色综合色狠狠综合色| 麻豆91在线看| 一区二区三区不卡视频在线观看| 精品电影一区二区| 欧美人体做爰大胆视频| 91蜜桃视频在线| 国产精品综合久久| 午夜电影一区二区三区| 亚洲女性喷水在线观看一区| 国产婷婷色一区二区三区| 欧美日韩综合一区| av电影天堂一区二区在线观看| 美女视频一区二区| 亚洲成国产人片在线观看| 最新久久zyz资源站| 国产婷婷色一区二区三区在线| 欧美一卡2卡三卡4卡5免费| 在线观看亚洲精品| 95精品视频在线| 成人毛片视频在线观看| 国产乱码精品一区二区三区忘忧草| 奇米影视在线99精品| 午夜精品一区二区三区电影天堂| 日韩码欧中文字| 亚洲欧洲日产国码二区| 国产精品久久久久久久蜜臀| 国产三级精品三级| 2021久久国产精品不只是精品| 欧美精品在线一区二区| 欧美亚洲动漫精品| 欧美日韩综合不卡| 欧美日韩国产美| 欧美高清视频不卡网| 宅男在线国产精品| 日韩午夜在线播放| 欧美www视频| 久久久久久久久免费| 中文字幕欧美日韩一区| 日韩一区在线播放| 亚洲亚洲人成综合网络| 午夜精品成人在线视频| 日韩成人一级大片| 激情六月婷婷久久| 成人免费va视频| 91国产免费看| 欧美剧情片在线观看| 日韩精品专区在线影院重磅| 久久女同互慰一区二区三区| 国产精品视频一二三| 亚洲精品国产第一综合99久久| 亚洲图片欧美综合| 久久9热精品视频| 粉嫩绯色av一区二区在线观看| caoporen国产精品视频| 色丁香久综合在线久综合在线观看| 欧美在线短视频| 欧美一区二区三区婷婷月色| 日韩一二三区不卡| 欧美激情一区三区| 一区二区三区不卡在线观看| 青青草伊人久久| 成人国产亚洲欧美成人综合网| 91网址在线看| 欧美sm极限捆绑bd| 中文字幕在线一区二区三区| 亚洲成人免费电影| 国产成人在线免费观看| 91高清视频免费看| 久久久亚洲精华液精华液精华液| 亚洲精品videosex极品| 激情丁香综合五月| 欧美日韩一区二区三区免费看| 久久综合色婷婷| 亚洲一区在线观看免费观看电影高清| 日韩成人av影视| 在线观看国产91| 国产日产欧美一区| 日韩成人免费电影| 在线观看中文字幕不卡| 国产视频不卡一区| 免费黄网站欧美| 在线看国产日韩| 国产精品福利在线播放|