如何在vi编辑器中修改文件权限

29

我有时候会在vi中打开只读文件,忘记在打开之前执行chmod +w。有没有办法在vi内部更改文件?

类似于 !r chmod +w [文件名] 的方式吗?

是否有一种快捷方式可以引用当前打开的文件而无需拼写其长名称?

9个回答

67

只需使用

:!chmod +w %
在命令模式下。% 将被替换为当前文件名。

3
谢谢,这个很有用。一个小烦恼是vim现在会警告需要重新加载文件(W16)。是否有一种方法可以停止它而不设置autoread? - Rmano
1
@Rmano 我知道这是一个旧帖子,但值得提及的是:您可以使用 Tim Pope 的 Eunuch.vim 然后使用 :Chmod 命令。它完全符合您的要求。 - evanthegrayt

38

如果你有写文件的权限,那么你可以使用感叹号来强制执行:

:w!

如果您没有权限并需要更改用户,但仍然想要写入文件,有时可以尝试以下方法:

:w !sudo tee %

3
你也不希望一直写入文件的;-) - Michael Krelin - hacker
1
:w !sudo tee % 命令会将文件输入发送到 tee,然后将其转发到当前文件 % - Lubo Kanev
@LuboKanev,没错。作为副作用,“tee”也会将文件写入控制台,但这并不是为了实现任何目的;-) - Michael Krelin - hacker

13

我知道这是一个旧帖子,但在 Vim Version8 中已经包含了一个函数,可以更改文件权限。

根据 version8.txt 文件:

setfperm() 设置文件的权限

然后可以通过Vim中的“call”命令调用此函数。

操作步骤如下:

:call setfperm("file name","permissions")

"权限"字符串的结构与Vim文档中描述的形式相同:

getfperm({fname}) getfperm() 结果是一个字符串,表示给定文件{fname}的读、写和执行权限。如果{fname}不存在或其目录无法读取,则返回空字符串。 结果的形式为“rwxrwxrwx”,其中每组“rwx”标志依次表示文件所有者、所属组和其他用户的权限。 如果用户没有给定的权限,则用字符串“-”替换该标志。例如: :echo getfperm("/etc/passwd") 这将从安全角度(希望如此)显示字符串“rw-r--r--”甚至是“rw-------”。

一个最简示例:

:call setfperm("foo.txt","rwxrwxrwx")

这会在当前目录下的“foo.txt”文件中添加读取、写入和执行权限。


3
setfperm() 函数也出现在 Vim 7 中(至少,7.4 版本有它)。:call setfperm(expand("%"), "rwxr-xr-x") 是一种设置当前文件模式为 0755 的方式,无需明确输入文件名。 - the paul

7
你尝试过了吗?
!chmod +w %

% 表示当前文件名。

你也可以将一个键映射到它,比如 Ctrl-W。

:map <C-w> :!chmod +w %<CR>

请注意,要输入 "<CR>",您需要按下 Ctrl-V Ctrl-M。

5
在使用vim编辑文件后,按下"esc"键,然后输入":"。接着输入以下命令:
w !sudo tee %

然后按“Enter”键。 然后输入

:q!

要成功退出编辑器。


谢谢@Kasumi!这就是我正在寻找的内容——如何切换用户并使用它的所有者(在我的情况下为root)编写文件。 - Беров

1
:!chmod <perms> <file>

如果vi仍然不想写它,

:se cpo-=W

0

如果您很懒,也可以使用vim自带的netrw模块来完成此操作,例如:Texplore ,然后在正常模式下滚动到文件并输入 gp 。 八进制或符号至少有效。

对于多个文件来说,这种方法可能有点棘手,但是对于单个缓冲区窗口而言,可以使用冒号命令历史记录重复命令,会更加直观一些。


0
正如David所指出的那样,setfperm()是在vim中执行此操作的方法。
以下是我用来添加当前文件写入或执行权限的映射:
function! ChmodPlus(expr, pat)
    let file = expand('%')
    let oldperms = getfperm(file)
    let newperms = substitute(oldperms, a:expr, a:pat, '')
    if (oldperms != newperms)
        call setfperm(file, newperms)
    endif
    echom(printf('Permissions: %s', newperms))
endfunction

function! ChmodPlusX()
    call ChmodPlus('^\(..\).', '\1x')
endfunction

function! ChmodPlusW()
    call ChmodPlus('^\(.\).', '\1w')
endfunction

" Make current file writeable
noremap <silent> <Leader>W :call ChmodPlusW()<CR>

" Make current file executable
noremap <silent> <Leader>X :call ChmodPlusX()<CR>

0
根据这里的几个答案的想法,我现在正在使用这个:
" autoreload file
set autoread

" chmod +x current file
"
" not using setfperm() here to have the behavior of chmod(1), e.g. adding and
" using the umask.
function! ChmodThis(perm)
  if getbufinfo('%')[0].changed
    echo "Modified, save first!"
  else
    call system('chmod ' .. a:perm .. ' -- ' .. expand('%:S'))
    echo "chmod done."
  endif
endfunction
noremap <silent> <Leader>X :call ChmodThis('+x')<CR>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接