Vim 编辑文件的过程分为三步:
1. 将文件读入缓冲区
2. 通过编辑器命令修改缓冲区
3. 将缓冲区写回文件
current-file
只要不执行缓冲区写回,原始文件就不会被修改。开始编辑文件时 (将文件读入缓冲
区),该文件名会被记录为 "当前文件名",也称为当前缓冲区名。在命令行上,可用 "%"
引用该名字 :_% 。
alternate-file
如果编辑前已经存在另外一个当前文件名,该文件名会成为轮换文件名。在命令行上,可
用 "#" 引用该名字 :_# 。还可用 CTRL-^ 命令在当前和轮换文件间快速切换。但使
用 :keepalt 期间,轮换文件名会保持不变。每个窗口都会独立记录其轮换文件名。
:keepa :keepalt
:keepa[lt] {cmd} 执行 {cmd},在此期间保持当前轮换文件名不变。注意 间接
调用的命令 (例如通过函数调用) 仍可能修改轮换文件名。
所有文件名都会记录在缓冲区列表中。输入文件名用于编辑 (如 `:e 文件名`) 或写入
(如 `:w 文件名`) 时,该文件名会被加入列表。可用缓冲区列表记住编辑过的文件,然
后通过 CTRL-^ 命令在文件间快速切换 (例如用于复制文本)。为此,先键入文件编号,
再按 CTRL-^。
CTRL-G 或 CTRL-G :f :fi :file
:f[ile] 显示当前文件名 (除非使用过 :cd ,否则应显示输入时使用
的简短名)、光标位置 (如果未开启 'ruler' 选项) 和文件状
态 (只读、已修改、读错误、新文件)。可通过 'shortmess'
选项精简此消息。
:f[ile]! 和 :file 类同,但忽略 'shortmess' shm-t 标志位,不
会截短文件名。
{count}CTRL-G 和 CTRL-G 类同,但显示完整路径的当前文件名。计数大于
1 时,同时显示当前缓冲区号。(译者注: 计数为 0 时的行为
相当于无计数的 CTRL-G)
g_CTRL-G word-count byte-count
g CTRL-G 以五种方式显示当前光标位置: 列、行、单词、字符和字节计
数 (译者注: 显示格式为 "当前计数/文件总计数")。如果字
符数和字节数相同,省略字符位置的显示。
如果当前行存在占据多于一个位置的字符 (<Tab> 或其他特殊
字符),或单列占用多字节的字符 ('encoding' 为 utf-8 时
值大于 0x7F 的字符),在显示列的位置会同时显示字节列和
屏幕列,以连字号分隔。
另见 'ruler' 选项和 wordcount() 函数。
v_g_CTRL-G
{Visual}g CTRL-G 在可视模式下,和 "g CTRL-G" 类同,但显示可视选区的单
词、字符、行和字节计数。在面向列块模式下,还会显示列
数 (关于 {Visual},参见 Visual-mode )。
:file_f
:f[ile][!] {name} 将当前文件名设为 {name}。同时显示新的当前文件名,和
:file 一样,可选的 ! 可避免截短消息。
如果缓冲区已有当前文件名,该名会成为 alternate-file
轮换文件名。此时,会新建一个列表外缓冲区来保存旧名。
:0file
:0f[ile][!] 移除当前缓冲区的文件名。同时显示新的当前文件名 (即
"未命名"),和 :file 一样,可选的 ! 可避免截短消息。
:buffers
:files
:ls 列出所有当前已知的文件名。详见 windows.txt :files
:buffers :ls 。
vim 会记住用户输入文件名的完整路径。多数情况下,显示输入时使用的简短名。但使用
过 :cd 命令后,会显示完整路径名。
home-replace
环境变量 $HOME 已设置时,以该路径开始的文件名,显示时会将 HOME 替换为 "~",使
显示尽量简洁。"~" 只用于显示,读写文件时仍使用完整路径。如果文件名替换后只剩
"~",会显示为 "~/" (避免设为 $HOME 的选项与 'backupext' 设置的 "~" 混淆)。另见
$HOME-windows 。
保存缓冲区时,缺省使用当前文件名。因此执行 ZZ 或 :wq 命令时,会覆盖原始文
件。如果不想如此,可为 :write 命令指定文件名参数,将缓冲区写入其他文件。
例如:
vim testfile
[用编辑器命令修改缓冲区]
:w newfile
:q
这会创建文件 "newfile","testfile" 的修改副本。原始文件 "testfile" 文件保持不
变。反正,在置位 'backup' 选项时,Vim 会在原始文件被覆盖前先对其重命名或复制生
成备份文件。后续需要原始版本时可直接使用。另见 'patchmode' 选项。备份文件名通
常为原始文件名加 'backupext' 后缀。缺省后缀 "~" 的特殊设计是为了防止意外覆盖已
有文件。如果习惯用 ".bak",修改 'backupext' 选项即可。在 MS-Windows 上,当 Vim
检测到 MS-DOS 兼容文件系统或 'shortname' 选项打开时,文件名中的多余点号会自动
替换成 '_'。
要将备份文件统一存放到其他目录,可通过设置 'backupdir' 实现。
auto-shortname
技术说明: Amiga 系统文件名可长达 30 个字符。但在 MS-DOS 兼容文件系统上只支持
8+3 个字符。Vim 创建交换文件 (".swp") 时会自动检测文件系统类型。如果
判定为 MS-DOS 兼容文件系统,则自动置位等效于开启 'shortname' 选项的
内部标志位。该标志位在打开新文件后自动复位,它仅用于生成当前文件的交
换文件和备份文件。如果编辑普通文件系统上的文件,然后写到 MS-DOS 兼容
文件系统上,则不会置位该标志位。因此创建备份文件 (".~") 可能会失败并
报错。这种场景需要手动打开 'shortname' 选项。
开始编辑而未给出文件名时,状态栏上会显示 "未命名"。此时如果执行带文件名参数的
:write 命令,会将该文件名设为当前文件名。该行为假定 'cpoptions' 里已包含 'F'
标志位 cpo-F (这是缺省),适用于在新建空缓冲区中输入文本后保存文件的场景。如
果 'cpoptions' 里包含 'f' 标志位 cpo-f (缺省 排除 ),在无名缓冲区上执行带文
件名参数的 :read 时,同样会将该文件名设为当前文件名。这适用于无参数启动 Vim
后通过 ":read file" 开始编辑的场景。
设置文件名而 'filetype' 尚为空时,会自动触发文件类型检测自动命令。
not-edited
仅设置文件名但未实际编辑文件时,Vim 会设置 "notedited" 内部标志位,防止误覆盖
文件。要查看该标志位状态,可按 CTRL-G 或 :file 命令。标志位开启时会显示
"[未编辑]"。向当前文件名写入缓冲区内容 (用 :w! ) 后,标志位被复位。
abandon
Vim 会记录缓冲区是否被修改。防止编辑内容意外丢失。缓冲区已改动时,试图不写回就
退出或切换文件都会被阻止。要绕过这重保护,可在相关命令后加 '!',强制忽略改动并
执行操作。此时改动内容会丢失。例如: :q 在缓冲区修改后无法退出,但 :q! 会强
制退出并丢弃修改。要查看缓冲区是否被修改,可按 CTRL-G。已修改会显示 "[已修改]"
或在 'shortmess' 包含 'm' 标志位时,显示 "[+]"。
如果希望不经提示自动保存所有改动,可打开 'autowriteall' 选项。'autowrite' 是相
关的 Vi-兼容选项,只对部分命令有效。
如果希望保留已修改的缓冲区但不保存改动,可打开 'hidden' 选项,放弃时自动隐藏而
不卸载缓冲区。参见 hidden-buffer 。有些命令无需开启 'hidden' 也可实现同样效
果,具体请参见命令帮助文档。
:e :edit reload
:e[dit] [++opt] [+cmd] 重新编辑当前文件。可在文件在 Vim 外部被修改时,重新进
行加载。如果当前缓冲区被修改,且未置位 'autowriteall'
或无法写入,本命令会失败。
另见 ++opt 和 +cmd 。
:edit! discard
:e[dit]! [++opt] [+cmd]
强制重新编辑当前文件。丢弃当前缓冲区的所有修改。适合想
从头重来时使用。
另见 ++opt 和 +cmd 。
:edit_f
:e[dit] [++opt] [+cmd] {file}
编辑指定文件 {file}。
如果当前缓冲区被修改,除非置位 'hidden'、或置位
'autowriteall' 且文件可写,否则本命令会失败。
另见 ++opt 和 +cmd 。
:edit!_f
:e[dit]! [++opt] [+cmd] {file}
强制编辑指定文件 {file}。丢弃当前缓冲区的所有修改。
另见 ++opt 和 +cmd 。
:edit_# :e#
:e[dit] [++opt] [+cmd] #[count]
编辑缓冲区列表中第 [count] 个缓冲区 (同 :files 显示
的编号)。
和 [count] CTRL-^ 类同,但 `:e #` 在轮换缓冲区无名时
会失效,而 CTRL-^ 仍然可用。
另见 ++opt 和 +cmd 。
:ene :enew
:ene[w] 编辑新无名缓冲区。如果当前缓冲区被修改,除非置位
'hidden'、或置位 'autowriteall' 且文件可写,否则本命令
会失败。
如果 'fileformats' 非空,新缓冲区会使用其中首个格式。
否则,使用当前缓冲区设置的 'fileformat'。
:ene! :enew!
:ene[w]! 编辑新无名缓冲区。丢弃当前缓冲区的所有修改。
'fileformat' 的设置方式可见 :enew 。
:fin :find
:fin[d][!] [++opt] [+cmd] {file}
在 'path' 指定的路径中找到 {file},然后用 :edit 对其
进行编辑。
另见: 'findfunc'。
:{count}fin[d][!] [++opt] [+cmd] {file}
和 ":find" 类同,但使用 'path' 里找到的第 {count} 个匹
配文件。例如,`:2find file` 会找到 'path' 里找到的第二
个 "file"。如果找到的数量不足此数,会报错。
:ex
:ex [++opt] [+cmd] [file]
同 :edit 。
:vi :visual
:vi[sual][!] [++opt] [+cmd] [file]
用于 Ex 模式时: 退出 Ex-mode ,回到普通模式。
否则同 :edit 。
:vie :view
:vie[w][!] [++opt] [+cmd] file
用于 Ex 模式时: 退出 Ex-mode ,回到普通模式。
否则和 :edit 类同,但为本缓冲区置位 'readonly' 选
项,设为只读。
CTRL-^ CTRL-6
CTRL-^ 编辑轮换文件。
轮换文件通常就是上次编辑的文件。这是一种在两个文件间快
速切换的方法。和 `:e #` 等价,但也能用于无名轮换文件。
如果当前缓冲区被修改,且 'autowrite' 或 'autowriteall'
选项打开,则先自动保存当前文件。
^ 字符通常位于 6 键上,因此同时按下 CTRL 和 6 就会生成
称为 CTRL-^ 的键码。但在某些非美式键盘上,CTRL-^ 的输
入方式可能不同。
[count]CTRL-^ 编辑缓冲区列表中第 [count] 个文件 (和 ":e #[count]" 等
价)。这是一种在文件间快速切换的方法。
详见上文 CTRL-^ 。
[count]]f ]f [f
[count][f 同 gf 。已废弃。
gf E446 E447
[count]gf 编辑光标所在或光标后的文件名对应的文件。
助记: "goto file" (转到文件)。
'isfname' 选项用于判定组成文件名的字符集。忽略拖尾的标
点符号 ".,:;!"。转义空格 "\ " 缩为普通空格。
在 'path' 选项目录名列表中查找文件。关于相对路径和通配
符的用法,详见 'path' 选项。
用 'suffixesadd' 选项尝试自动添加后缀。
如果找不到文件,用 'includeexpr' 转换文件名再试一次。
给出 [count] 时,打开 'path' 中找到的第 count 个文件。
如果 Vim 拒绝放弃 abandon 当前文件,本命令会失败。
要在新窗口里编辑该文件,可用 CTRL-W_CTRL-F 。
如果确实希望编辑尚不存在的文件,可用:
:e <cfile>
要让 gf 总是使用此工作方式,可用:
:map gf :e <cfile><CR>
要能打开 "type://machine/path" 形式的超文本链接,需要
netrw 插件。
在 Unix 上,会扩展 "~user/file" 等形式中的 '~' 字符,
也会扩展环境变量 expand-env 。
v_gf
{Visual}[count]gf 在可视模式下,和 gf 类同,但使用高亮选中文本作为文件
名进行编辑。这里不考虑 'isfname' 选项。
跳过起始空白,除此以外,所有的空白和特殊字符都被作为文
件名的一部分 (关于 {Visual},参见 Visual-mode )。
gF
[count]gF 和 gf 类同,但文件名后跟行号时,会自动跳转到指定行。
文件名和数值间必须以一个非文件名 (见 'isfname') 且非数
位的字符分隔。也识别 `:verbose command UserCmd` 输出使
用的 " 行 " 分隔串 (翻译版本或英语版本 " line ")。忽略
文件名、分隔符和数值之间的空白。
支持格式示例:
eval.c:10
eval.c @ 20
eval.c (30)
eval.c 40
eval.c 行 50
v_gF
{Visual}[count]gF 同 v_gf 。
这些命令用于打开并编辑单个文件。具体是,将文件读入缓冲区、同时设置当前文件名、
具体打开的文件和当前目录有关,见 :cd 。
文件读取完成后给出的提示消息,可见 read-messages 。
如果缓冲区修改错乱想从头再来,可用 :e! 命令。 :e 命令仅当修改过当前文件名后
才会生效。
:filename {file}
除了这里说明的事项以外,命令行中文件名的特殊写法可见 cmdline-special 。
注意 非 Unix 系统上: 仅接受单个文件名的命令 (如 `:edit file`) 中,文件名可内嵌
空格,但忽略拖尾空格。适用于 MS-Windows、Amiga 等文件名中经常带空格的系统。示
例: 命令 ":e Long File Name " 实际打开的文件是 "Long File Name"。可接受多个
文件名的命令 (如 `:next file1 file2`) 中,文件名内嵌空格必须以反斜杠转义。
wildcard wildcards
{file} 里会自动展开通配符,但和文件补全一样,也适用 'wildignore' 和 'suffixes'
规则。具体支持通配符的种类随系统略有差异。通用通配符如下:
? 匹配单个任意字符
* 匹配任意长度文本,包括空文本
** 匹配任意长度文本,包括空文本,然后递归进入任意层级的子目录
[abc] 匹配 'a'、'b' 或 'c'
要取消通配符的特殊含义,可前置反斜杠转义。不过,在 MS-Windows 上,反斜杠本身是
路径分隔符,如果 'isfname' 选项包含 "[","path\[abc]" 还是将 "[abc]" 看作通配
符。简单的解决方法是写作 "path\[[]abc]"。确保匹配文件名 "path\[abc]"。
starstar-wildcard
在 Unix、Win32、macOS 等系统上,支持 "**" 通配符 (Unix 和 macOS 上也取决于
'shell' 设置。已知 zsh 可用;bash 需要 4.X 及以上版本)。
此通配符可递归检索目录树,最大检索深度为 100 层目录。
注意 部分命令匹配逻辑有细微差别。详见 file-searching 。
例如:
:n **/*.txt
会匹配到以下文件:
aaa.txt
subdir/bbb.txt
a/b/c/d/ccc.txt
"**" 前后紧邻非通配字符时,仅在第一层目录上匹配,不会匹配递归深层目录名。
例如:
:n /usr/inc**/types.h
会匹配到以下文件:
/usr/include/types.h
/usr/include/sys/types.h
/usr/inc/old/types.h
注意 会包含带 "/sys" 的路径,因为子目录名不需要匹配 "/inc"。原理上,该模式等价
于 "/usr/inc*/*/*...",而非 "/usr/inc*/inc*/inc*"。
backtick-expansion `-expansion
在 Unix 及部分其他系统上,可在文件名参数位置上,使用反引号记法执行外部命令生成
文件名。例如:
:next `find . -name ver\\*.c -print`
:view `ls -t *.patch \| head -n1`
Vim 会通过 'shell' 执行反引号内的命令,并将其标准输出作为 Vim 命令的参数 (外壳
命令的错误信息会被丢弃)。
要看到 Vim 执行的具体外壳命令,可将 'verbose' 选项设为 4。如果外壳命令返回非零
退出码,报错并中止当前 Vim 命令。要避免这种情况,可让外壳命令永远返回零值,例
如:
:next `find . -name ver\\*.c -print \|\| true`
星号前需要反斜杠转义,用于防止 "ver*.c" 在执行 find 前先被外壳展开。
外壳管道符 "|" 前也需要反斜杠转义,用于防止 Vim 将其解析为命令终止符。
该功能在大多数其他系统上都可用,但有附加限制,反引号必须包围整个项目。其前后不
能附加其他文本。
`= E1083
在首个反引号后紧跟等号,可使反引号内容用作 Vim 表达式来执行,而非外部命令。例
如:
:e `=tempname()`
该表达式可包含任意内容,因而也可用于取消 '"'、'|'、'%' 和 '#' 字符的特殊含义。
不过,和其它文件通配符一样,'wildignore' 同样适用于此表达式结果。
执行表达式前,会先扩展表达式里的环境变量,例如:
:e `=$HOME .. '/.vimrc'`
但字符串内部的 $HOME 会按本义使用而不会被扩展,这可能出乎意料,例如:
:e `='$HOME' .. '/.vimrc'`
表达式返回字符串时,用换行符分隔多个文件名。返回 List 时,每个列表项视作一个
文件名。但列表项内也可用换行符分隔多个文件名。
注意 此语法仅支持在 Ex 命令中需要文件名参数的位置上使用。
++opt [++opt]
[++opt] 参数可为一条命令单次强制指定 'fileformat'、'fileencoding' 或 'binary'
值、或指定非法字符的处理方式。其格式是:
++{optname}
或:
++{optname}={value}
其中 {optname} 可用值为: ++ff ++enc ++bin ++nobin ++edit
ff 或 fileformat 覆盖 'fileformat' 值
enc 或 encoding 覆盖 'fileencoding' 值
bin 或 binary 置位 'binary'
nobin 或 nobinary 复位 'binary'
bad 指定非法字符的处理方式
edit 只用于 :read : 按编辑文件方式设置相应选项值
{value} 不能包含空白。且必须是对应选项的合法值。例如:
:e ++ff=unix
会以 'fileformat' 为 "unix" 方式重新加载当前文件。
:w ++enc=latin1 newfile
会以 latin1 编码将当前缓冲区写入 "newfile"。
当 'fileencoding' 或 ++enc 指定值与 'encoding' 不一致时,写入文件后会显示
"[已转换]" 消息。
可以同时使用多个 ++opt 参数,以空格分隔。且必须放在所有 +cmd 参数之前。
++bad
"++bad=" 参数用于指定无法转码的字符与非法字节的处理规则。可为以下三种形式之一:
++bad=X 用单字节字符 X 替换每个异常字符。
++bad=keep 保留异常字符不予转化。注意 这可能导致文本中出现非法字节!
++bad=drop 直接删除异常字符。
缺省行为相当于 "++bad=?": 用问号替换每个异常字符。有些场景会使用倒转问号 ¿
(0xBF)。
注意 并非所有命令都使用 ++bad 参数 (如 :write ),但不会报错。
注意 读入文件时,'fileformat'、'fileencoding' 和 'binary' 选项会被即时更新为指
定值。写入文件时则不会实际更新选项。后续保存操作仍沿用旧值。
+cmd [+cmd]
[+cmd] 参数可用于打开文件后定位光标或自动执行任意命令:
+ 光标跳转到末行。
+{num} 光标跳转到第 {num} 行。
+/{pat} 光标跳转到首个匹配 {pat} 的行。
+{command} 打开文件后,自动执行 Ex 命令 {command}。
要在 {pat} 或 {command} 里包含空白,要用反斜杠转义。反斜杠本身则要加倍。
:edit +/The\ book file
:edit +/dir\ dirname\\ file
:edit +set\ dir=c:\\\\temp file
注意 最后一例里反斜杠需要减半两次: 一次用于解析 "+cmd" 参数,一次用于 ":set"
命令。
file-formats
'fileformat' 选项指定文件行尾结束符 (<EOL>) 风格:
'fileformat' 行尾结束符 格式名称
"dos" <CR><NL> 或 <NL> DOS 格式 DOS-format
"unix" <NL> Unix 格式 Unix-format
"mac" <CR> Mac 格式 Mac-format
旧参数 'textmode' 已废弃。
读入文件时,上述字符被解释为行尾结束符。DOS 格式 (Win32 缺省值) 会把 <CR><NL>
和单独 <NL> 都解释为换行。注意 在以 DOS 格式写入文件时,单独 <NL> 会自动换为
<CR><NL>。另见 file-read 。
写入文件时,用上述字符输出行尾。DOS 格式统一使用 <CR><NL>。另见
DOS-format-write 。
可用 DOS 格式读入文件,再以 Unix 格式写回。下例会将所有的 <CR><NL> 对自动替换
为 <NL> (假定 'fileformats' 已包含 "dos"):
:e file
:set fileformat=unix
:w
反之,如用 Unix 格式读入文件,再以 DOS 格式写回,则所有的 <NL> 字符都会被自动
替换为 <CR><NL> 对 (假定 'fileformats' 已包含 "unix"):
:e file
:set fileformat=dos
:w
开始编辑新文件且 'fileformats' 选顶非空 (这是缺省) 时,Vim 会自动检测文件的行
尾结束符格式。设为 "unix,dos" 时,Vim 会检查换行是通过 <NL> (Unix 和 Amiga) 还
是 <CR><NL> 对 (MS-Windows)。仅当 所有 行都以 <CR><NL> 结尾时,'fileformat' 才
会被设为 "dos",否则设为 "unix"。'fileformats' 也包含 "mac" 且文件中完全不存在
<NL> 字符时,'fileformat' 才会被设为 "mac"。
非 MS-Windows 系统上,如果 'fileformat' 选项被设为 "dos",会显示 "[dos 格式]"
提示用户使用了非系统标准格式。类似地,在 MS-Windows 系统上,如果 'fileformat'
被设为 "unix",会显示 "[unix 格式]"。而在非 Mac 系统上,如果 'fileformat' 被设
为 "mac",会显示 "[mac 格式]"。
如果 'fileformats' 选项为空且使用 DOS 格式,但读取时发现部分行不以 <CR><NL> 结
尾,会显示 "[缺少 CR]"。
如果 'fileformats' 选项为空且使用 Mac 格式,但读取时发现 <NL> 的存在,会显示
"[NL missing]" (译者注: 原文如此,似不确,系统会自动将 <NL> 替换为 <CR> 而不特
别提示)。
如果新文件尚不存在,当 'fileformats' 为空时,会沿用当前缓冲区的 'fileformat',
否则使用 'fileformats' 列表中的首个格式。
编辑二进制文件、可执行文件或 Vim 脚本文件时,建议置位 'binary' 选项。最简单的
方式是启动 Vim 时加上 "-b" 参数。此时会忽略 'fileformat' 及相关处理,避免单独
<NL> 字符被意外替换成 <CR><NL> 对的风险。
通过设置 'key' 选项可对写入的文件进行加密。提供基础安全性,防止其他用户随意读
取文件内容。 encryption
行 尾 和 文 件 尾 格 式 eol-and-eof
Vim 用以下选项控制文件格式:
'fileformat' <EOL> 风格: Unix、DOS、Mac
'endofline' 末行是否以 <EOL> 结尾
'endoffile' 文件是否以 CTRL-Z 结尾
'fixendofline' 是否自动修正行尾和文件尾
前三项通常在读取文件时自动检测,写回文件时沿用。而在缓冲区编辑过程中,用户体验
则保持一致: 每行都会被视为以换行符结束,并且 CTRL-Z 不存在 (此规则不适用于
'binary' 置位时)。'fixendofline' 选项则用于控制写入行为。
用户也可手动修改这些选项值,使文件写入格式与读取时不同。
以下给出一些使用这些选项的实例。
强制使用 Unix 格式 (每行都以 NL 结尾):
setl ff=unix fixeol
推荐在类 Unix 的系统使用。现代 MS-Windows 系统也兼容。Vim 脚本建议总是使用此格
式。
在现代环境下使用古老的 MS-DOS 文件,修正行尾并删除 CTRL-Z,但保持 <CR><NL> 风
格的 <EOL>:
setl ff=dos fixeol
这适合常规使用 <CR><NL> 行尾的大多数 MS-Windows 程序。
要删除末行的 <EOL> 并加上 CTRL-Z 结尾 (如用于 CP/M 等老式系统):
setl ff=dos nofixeol noeol eof
要完全保留原始文件格式,不改动末行可能有的 <EOL> 或 CTRL-Z:
setl nofixeol
启动 Vim 时如果给出多个文件名,这些文件会被保存为参数列表。可在列表中的文件间
跳转。
不要与 :buffers 命令查看的缓冲区列表混淆。参数列表在 Vi 时代已经存在,而缓冲
区列表是 Vim 新增的。参数列表里的文件名一定会出现在缓冲区列表中 (除非被
:bdel 或 :bwipe 删除),但缓冲区列表中常有不在参数列表里的文件。
该主题的介绍请参考用户手册 07.2 一节。
有一个全局参数列表,所有窗口缺省使用全局列表。但窗口可创建局部的参数列表,见
:arglocal 。
要对参数列表进行操作,可见下列命令以及表达式函数 argc() 和 argv() 。他们均
作用于当前窗口的参数列表。
:ar :arg :args
:ar[gs] 显示参数列表,当前文件用方括号括出。
:ar[gs] [++opt] [+cmd] {arglist} :args_f
定义 {arglist} 为新参数列表,并编辑其中首个文件。
如果当前缓冲区已修改且 Vim 不允许放弃 abandon ,本命
令会失败。
另见 ++opt 和 +cmd 。
:ar[gs]! [++opt] [+cmd] {arglist} :args_f!
定义 {arglist} 为新参数列表,并编辑其中首个文件。丢弃
当前缓冲区的所有修改。
另见 ++opt 和 +cmd 。
:[count]arge[dit][!] [++opt] [+cmd] {name} ... :arge :argedit
将一到多个文件名 {name} 加入参数列表,并编辑其中首个文
件。
不检查重复,可重复添加同一文件 :argded 。
基本相当于先 :argadd 然后 :edit (唯一微小区别是
:edit 不修改参数列表,因此不更动参数列表指针)。
文件名内嵌空格需用 "\" 转义。
[count] 的用法可见 :argadd 。
如果当前文件无法被放弃 abandon ,{name} 等仍会被加入
参数列表,但不进行编辑。也不检查重复项。
另见 ++opt 和 +cmd 。
:[count]arga[dd] {name} ... :arga :argadd E479
:[count]arga[dd] E1156
将一到多个文件名 {name} 加入参数列表。{name} 省略时,
将当前缓冲区名加入参数列表。
[count] 省略时,{name} 会追加到参数列表当前项之后。否
则,添加到第 [count] 项之后。假定参数列表是 "a b c",
而当前参数为 "b",以下命令的效果分别为:
命令 新参数列表
:argadd x a [b] x c
:0argadd x x a [b] c
:1argadd x a x [b] c
:$argadd x a [b] c x
在最后一个命令之后再执行:
:+2argadd y a [b] c x y
不检查重复,可重复添加同一文件。但可用 :argdedupe 去
重:
:argadd *.txt | argdedupe
本命令不切换当前编辑文件。
注意: 也可用以下方法:
:args ## x
追加 "x" 项并对更新参数列表。
:argded[upe] :argded :argdedupe
移除参数列表里的重复文件名。如果当前文件是重复项,会将
当前文件改为相同文件在参数列表里首次出现的位置。
:argd[elete] {pattern} ... :argd :argdelete E480 E610
从参数列表里删除匹配一到多个 {pattern} 的文件。
{pattern} 为文件通配模式,见 file-pattern 。"%" 可用
来删除当前项 ( :_% )。
即使从列表中删除,当前编辑文件保持编辑状态不变。
例如:
:argdel *.obj
:[range]argd[elete] 从参数列表里删除编号在 [range] 范围内的文件。
例如:
:10,$argdel
删除第 10 个和这后所有文件,保留 1-9。
:$argd
只删除最后一个文件。
:argd
:.argd
删除当前文件。
:%argd
清空整个参数列表。
如果 [range] 的末数值超出实际范围,会一直删除到最后一
个参数。
:argu :argument
:[count]argu[ment] [count] [++opt] [+cmd]
编辑参数列表中第 [count] 个文件。[count] 省略时,编辑
当前项。如果当前缓冲区已修改且 Vim 不允许放弃
abandon ,本命令会失败。
另见 ++opt 和 +cmd 。
:[count]argu[ment]! [count] [++opt] [+cmd]
编辑参数列表中第 [count] 个文件。丢弃当前缓冲区的所有
修改。[count] 省略时,编辑当前项。
另见 ++opt 和 +cmd 。
:[count]n[ext] [++opt] [+cmd] :n :ne :next E165 E163
在参数列表中向后跳 [count] 个文件。如果当前缓冲区已修
改且 Vim 不允许放弃 abandon ,本命令会失败。
另见 ++opt 和 +cmd 。
:[count]n[ext]! [++opt] [+cmd]
在参数列表中向后跳 [count] 个文件。丢弃当前缓冲区的所
有修改。
另见 ++opt 和 +cmd 。
:n[ext] [++opt] [+cmd] {arglist} :next_f
同 :args_f 。
:n[ext]! [++opt] [+cmd] {arglist}
同 :args_f! 。
:[count]N[ext] [count] [++opt] [+cmd] :Next :N E164
在参数列表中向前跳 [count] 个文件。如果当前缓冲区已修
改且 Vim 不允许放弃 abandon ,本命令会失败。
另见 ++opt 和 +cmd 。
:[count]N[ext]! [count] [++opt] [+cmd]
在参数列表中向前跳 [count] 个文件。丢弃当前缓冲区的所
有修改。
另见 ++opt 和 +cmd 。
:[count]prev[ious] [count] [++opt] [+cmd] :prev :previous
同 :Next 。
另见 ++opt 和 +cmd 。
:rew :rewind
:rew[ind] [++opt] [+cmd]
跳转到参数列表首个文件。如果当前缓冲区已修改且 Vim 不
允许放弃 abandon ,本命令会失败。
另见 ++opt 和 +cmd 。
:rew[ind]! [++opt] [+cmd]
跳转到参数列表首个文件。丢弃当前缓冲区的所有修改。
另见 ++opt 和 +cmd 。
:fir :first
:fir[st][!] [++opt] [+cmd]
同 :rewind 。
:la :last
:la[st] [++opt] [+cmd]
跳转到参数列表末个文件。如果当前缓冲区已修改且 Vim 不
允许放弃 abandon ,本命令会失败。
另见 ++opt 和 +cmd 。
:la[st]! [++opt] [+cmd]
跳转到参数列表末个文件。丢弃当前缓冲区的所有修改。
另见 ++opt 和 +cmd 。
:wn :wnext
:[count]wn[ext] [++opt]
保存当前文件,然后在参数列表中向后跳 [count] 个文件。
另见 ++opt 和 +cmd 。
:[count]wn[ext] [++opt] {file}
保存当前文件到 {file},然后在参数列表中向后跳 [count]
个文件。如果 {file} 已存在且 'writeany' 选项关闭,本命
令会失败。
另见 ++opt 和 +cmd 。
:[count]wn[ext]! [++opt] {file}
强制保存当前文件到 {file},然后在参数列表中向后跳
[count] 个文件。另见 ++opt 和 +cmd 。
:[count]wN[ext][!] [++opt] [file] :wN :wNext
:[count]wp[revious][!] [++opt] [file] :wp :wprevious
和 :wnext 类似,但向前跳而不是向后跳。
以上命令的 [count] 缺省值为一。某些命令支持写两个计数。以最右侧数值为准。
[+cmd] 参数省略时,光标会定位于文件上一次退出时的位置。置位 'startofline' 时,
光标会定位于该行首个非空白字符,否则,使用上次的列位置。如果没有历史位置,光标
会定位在第一行 (Ex 模式下则是最后一行)。
{arglist}
参数列表中的通配符会自动展开,文件名会自动排序。例如用命令 "vim *.c" 可一次性
编辑所有 C 文件。在 Vim 内部,可用 `:n *.c` 命令达到相同效果。
参数列表中,空白用于分隔文件名。文件名内嵌空格或制表时,必须在前面加上反斜杠进
行转义。例如,要编辑单个名为 "foo bar" 的文件:
:next foo\ bar
在 Unix 和部分其他系统上,还可用反引号记法 backtick-expansion ,例如:
:next `find . -name \\*.c -print`
星号前需要反斜杠转义,用于防止 "*.c" 在执行 find 前先被外壳展开。
arglist-position
编辑参数列表中的文件时,可在窗口标题上看到当前编辑文件位置 (假定有窗口显示且
'title' 被置位),也可查看 "CTRL-G" 命令显示的文件消息。显示格式形如
(文件 4/11)
'shortmess' 包含 'f' 时,则显示为
(4/11)
如果并未编辑参数列表的当前文件,显示为
(文件 (4)/11)
这表示当前位于参数列表的第四个位置,但当前打开的不是列表里的第 4 个文件 (例如
手动执行了 `:e file`)。
局 部 参 数 列 表
:arglocal
:argl[ocal] 将全局参数列表复制一份,作为当前窗口的局部备份。不切换
当前编辑文件。
:argl[ocal][!] [++opt] [+cmd] {arglist}
直接定义 {arglist} 为新的当前窗口的局部参数列表。余同
:args_f 。
:argglobal
:argg[lobal] 当前窗口重新使用全局参数列表。不切换当前编辑文件。
:argg[lobal][!] [++opt] [+cmd] {arglist}
当前窗口重新使用全局参数列表。定义 {arglist} 为新的全
局参数列表,余同 :args_f 。所有使用全局参数列表的窗口
都会同步生效。
系统存在多个参数列表。窗口间可共享列表。共享时,其中任意一个窗口修改参数列表
时,其他窗口也会随之更新。
窗口分割时,新窗口会继承原窗口的参数列表。两个窗口因而共享同一个列表,直到其中
一个窗口通过 :arglocal 或 :argglobal 切换到其他参数列表为止。
使 用 参 数 列 表
:argdo
:[range]argdo[!] {cmd} 对参数列表里的每个文件执行 {cmd}。[range] 给出时,只对
编号在指定范围内的文件执行。这相当于:
:rewind
:{cmd}
:next
:{cmd}
依次类推
不带 [!] 时,如果当前缓冲区已修改且 Vim 不允许放弃
abandon ,本命令会失败。
任意一个文件执行 {cmd} 时如果出错,立即停止后续执行。
参数列表里最后停留的文件 (包括出错的文件) 会成为新的当
前文件。
{cmd} 可包含 '|',连接并执行多条命令。
{cmd} 命令执行期间,不能修改参数列表本身。
注意: 命令执行期间,会临时屏蔽 Syntax 自动命令事件 (通
过将其加入 'eventignore')。从而显著提高文件编辑速度。
另见 :windo 、 :tabdo 、 :bufdo 、 :cdo 、 :ldo 、
:cfdo 和 :lfdo
示例:
:args *.c
:argdo set ff=unix | update
将所有 *.c 文件的 'fileformat' 设为 "unix",如果因此导致文件被修改则保存改动
(从而确保所有 *.c 文件都使用 Unix 换行符)。
示例:
:args *.[ch]
:argdo %s/\<my_foo\>/My_Foo/ge | update
在所有 *.c 和 *.h 文件里,将完整单词 "my_foo" 替代成 "My_Foo"。"e" 标志位会使
:substitute 命令在文件中未匹配 "my_foo" 时不报错。 :update 确保仅在有修改时
才保存文件。
注意: 'write' 选项关闭时,无法写入任何文件。
:w :write
E502 E503 E504 E505
E512 E514 E667 E949
:w[rite] [++opt] 将整个缓冲区写入当前文件。这是保存文件修改的标准方式。
如果置位 'readonly' 选项或因其他原因无法写入,本命令会
失败。
关于 ++opt 可见 ++opt ,仅 ++bin、++nobin、++ff 和
++enc 有效。
:w[rite]! [++opt] 和 ":write" 类似,但即使 'readonly' 已置位或因其他原因
写入被拒绝,还是强制执行。
注意: 这可能会改变文件权限、所有者,以及破坏 (符号) 链
接。在 'cpoptions' 里加上 'W' 标志位可以避免覆盖只读文
件。
:[range]w[rite][!] [++opt]
只将 [range] 范围内的行写入当前文件。这不常用,因为会
导致文件不包含缓冲区全部内容。
:w_f :write_f
:[range]w[rite] [++opt] {file}
将 [range] 范围内的行另存文件 {file}。如果 {file} 已存
在且 'writeany' 选项关闭,本命令会失败。
:w!
:[range]w[rite]! [++opt] {file}
将 [range] 范围内的行强制另存文件 {file}。已存在的文件
会被覆盖。
:w_a :write_a E494
:[range]w[rite][!] [++opt] >>
将 [range] 范围内的行追加到当前文件末尾。
:[range]w[rite][!] [++opt] >> {file}
将 [range] 范围内的行追加到文件 {file} 末尾。'!' 会强
制写入尚不存在的文件,否则追加到尚不存在的文件会报错。
:w_c :write_c
:[range]w[rite] [++opt] !{cmd}
执行命令 {cmd},以 [range] 范围内的行作为标准输入。
(注意 ! 之前必须有空格)。{cmd} 的执行方式和 ":!{cmd}"
相同,{cmd} 里的 '!' 会被替换成前次外部命令,见 :! 。
:w 命令的缺省 [range] 是整个缓冲区 (1,$)。 '[ 和 '] 位置标记会分别被设为
写入命令的 [range] 的开始和结束位置。写回整个缓冲区时,缓冲区不再被认为已修
改。用 `:w somefile` 另存其他文件时,此行为取决于 'cpoptions' 里的 "+" 标志位
cpo-+ 。包含时,即便缓冲区仍然和关联文件不同步,'modified' 标志位还是被复位。
:w 显式指定的文件名会成为轮换文件。如果写入失败而稍后想重试,可据此将命令简
化为 ":w #"。从 'cpoptions' 选项里排除 'A' 标志位可关闭此特性。
注意 'fsync' 选项置位时,写操作会变慢,但更安全。
:sav :saveas
:sav[eas][!] [++opt] {file}
将当前缓冲区另存为文件名 {file},并将其设置为当前缓冲
区的文件名。原文件名成为轮换文件名。[!] 会强制覆盖已存
在的文件。
'filetype' 为空时,在写入文件前,会根据新名进行文件类
型检测。
成功写入后,复位 'readonly'。
:up :update
:[range]up[date][!] [++opt] [>>] [file]
和 :write 类似,但只在缓冲区已修改时才真正写入。
写 入 多 个 缓 冲 区 buffer-write
:wa :wall
:wa[ll] 保存所有已修改的缓冲区。无名缓冲区会报错。只读缓冲区会
被跳过。
:wa[ll]! 保存所有已修改的缓冲区,包括只读缓冲区。无名缓冲区仍然
不会保存并报错。
如果试图覆盖在 Vim 外部被修改的文件,Vim 会给出警告。参见 timestamp 。
backup E207 E506 E507 E508 E509 E510
覆盖已存在的文件 (不包括追加模式) 且 'backup'、'writebackup' 或 'patchmode' 选
项已打开时,会自动为原始文件创建备份。备份可通过复制或换名方式 (详见
'backupcopy')。成功写入后,如果 'writebackup' 选项置位但 'backup' 复位,备份文
件会被自动删除。而当 'patchmode' 选项打开时,备份文件可能会被改名。
备份行为总结如下:
backup-table
'backup' 'writebackup' 行为
关闭 关闭 不创建备份
关闭 打开 创建临时备份,成功写入后删除 (缺省)
打开 关闭 删除旧备份,创建新备份
打开 打开 删除旧备份,创建新备份
如果写入的文件名匹配 'backupskip' 模式,不创建备份文件。此时,忽略 'backup' 和
'writebackup' 设置。
'backup' 选项置位时,先删除旧备份文件 (与新备份文件同名)。未置位 'backup' 但置
位 'writebackup' 时,不会删除已有的备份文件。新备份会使用其他文件名。
在某些文件系统上,崩溃可能导致备份文件及新文件同时丢失 (或数据错误)。此时可尝
试修复功能 :recover ,因为交换文件同步到物理磁盘,也许仍然可用于救回数据。
'backupdir' 选项指定存放备份文件的目录 (缺省与原文件同目录)。
'backupcopy' 选项决定备份方式,是通过复制原文件到新建副本、还是通过换名原文
件。具体何时使用哪种机制,详见选项文档。
如果备份文件创建失败,不会继续执行写入操作。但可在命令后加上 '!',强制这种情况
下仍然继续完成写入。
file-watcher
如果某些监听文件写入事件的工具 (如 inotify、entr 或 fswatch),或调用 Vim 编辑
文件的外部程序 (如 git) 无法检测到原文件已被修改,可以考虑将 'backupcopy' 选项
设为 "yes"。这样 Vim 会直接写入原文件而非创建新文件,从而确保这些监视程序能够
正确检测到文件变化。另见 crontab 。
write-permissions
写入新文件时,文件权限缺省为可读写。unix 上对应掩码是 0o666 外加 umask。写回
Vim 已读入的文件时,Vim 会保留原有权限,但清除特殊权限位 (SUID/SGID 等)。
write-readonly
'cpoptions' 选项里包含 'W' 时,Vim 拒绝覆盖只读文件。否则, :w! 可强制覆盖只
读文件,只要系统支持 (目录必须可写)。
write-fail
如果新文件写入失败,必须格外小心,避免同时丢失修改内容 和 原文件。如果未创建备
份文件而新文件写入失败,原文件实际已丢失!在成功保存文件前,千万不要直接退出
Vim!如果已创建备份,则会尝试从中恢复原文件 (如有可能)。此时即使退出 Vim 并丢
失当前修改,原文件通常仍可保留。如果恢复原文件失败,会报错,提示原文件已丢失。
DOS-format-write
'fileformat' 为 "dos" 时,<CR><NL> 用作行尾结束符 <EOL>。这是 Win32 缺省行为。
在其他系统上,会显示 "[dos 格式]" 信息,提示用户使用了非系统标准格式。
Unix-format-write
'fileformat' 为 "unix" 时,<NL> 用作行尾结束符 <EOL>。在 Win32 上会显示
"[unix 格式]" 信息。
Mac-format-write
'fileformat' 为 "mac" 时,<CR> 用作行尾结束符 <EOL>。在非 Mac 系统上会显示
"[mac 格式]" 信息。
另见 file-formats 、'fileformat' 以及 'fileformats' 选项。
ACL
ACL 代表访问控制表 (Access Control List)。这是控制文件访问权限的高级方法。在新
版 MS-Windows 和 Unix 系统上使用,但需要文件系统支持。
Vim 写入文件时尽力保留 ACL 信息。备份文件会继承原文件的 ACL。
打开文件时,ACL 信息也被用来检查文件是否只读。
xattr E1506 E1508 E1509
xattr 代表扩展属性 (Extended Attributes)。是文件系统中用于随文件一同存储元数据
的高级机制。该功能依赖于底层文件系统。Vim 仅在 Linux 系统上提供支持。
Vim 写入文件时尽力保留扩展属性信息。备份文件会继承原文件的扩展属性。
read-only-share
当 MS-Windows 共享网络驱动器时,可标记其为只读共享。此时即使文件本身没有只读属
性,NT 网络共享驱动器的 ACL 设置也允许写入,依旧无法保存文件。Win32 平台上的
Vim 可自动检测这类只读网络驱动器,并将其中文件标为只读。此时 :write 无法强行
写入。
write-device
目标文件名实际为设备名时,Vim 不会创建备份 (也无法创建)。又因为设备已经存在,
必须使用 "!" 强制写入。
Unix 上的示例:
:w! /dev/lpt0
MS-Windows 上:
:w! lpt0
Unix 上,当路径既不是普通文件也不是目录时,都会被判定为设备。fifo 和命令管道都
视同设备。MS-Windows 上,则通过匹配以下特殊名称 (大小写不限) 来判定是否设备:
AUX
CON
CLOCK$
NUL
PRN
COMn n=1,2,3... 等
LPTn n=1,2,3... 等
:q :quit
:q[uit] 退出当前窗口。最后一个编辑窗口 (见 edit-window ) 退出
后,会直接退出 Vim。如果当前缓冲区已修改且 Vim 不允许
放弃 abandon ,或者参数列表中还有文件未被编辑,本命令
会失败。
有其它标签页存在时,退出当前标签页的最后一个窗口会同时
关闭当前标签页本身 tab-page 。
触发 QuitPre 自动命令事件。
要退出其他窗口,可见 CTRL-W_q 。
:conf[irm] q[uit] 退出当前窗口,但如果当前缓冲区已修改,或者参数列表中还
有文件未被编辑,会提示确认。
见 :confirm 和 'confirm'。
:q[uit]! 强制退出当前窗口不保存,丢弃所有修改。直接卸载当前缓冲
区,不受 'hidden' 选项影响。
强制退出最后一个窗口时,如果有已修改的隐藏缓冲区,放弃
当前缓冲区,并切换到首个已修改的隐藏缓冲区。
要彻底强制退出,可用 :qall! 。
:cq[uit] 无条件强制退出 Vim 不保存,同时返回错误退出码。见
:cq 。可用于 Manx 的快速修复模式 (见 quickfix )。
:wq
:wq [++opt] 保存当前文件并关闭窗口。最后一个编辑窗口 (见
edit-window ) 关闭后,会直接退出 Vim。
如果文件只读或者缓冲区无名,则保存操作失败。如果参数列
表中还有文件未被编辑,则退出操作失败。
:wq! [++opt] 强制保存当前文件并关闭窗口。最后一个编辑窗口 (见
edit-window ) 关闭后,会直接退出 Vim。但如果缓冲区无
名,保存操作仍会失败。
:wq [++opt] {file} 另存为 {file} 并关闭窗口。最后一个编辑窗口 (见
edit-window ) 关闭后,会直接退出 Vim。如果参数列表中
还有文件未被编辑,则退出操作失败。
:wq! [++opt] {file} 强制另存为 {file} 并关闭窗口。最后一个编辑窗口 (见
edit-window ) 关闭后,会直接退出 Vim。
:[range]wq[!] [++opt] [file]
同上,但只写入 [range] 范围内的行。
:x :xit
:[range]x[it][!] [++opt] [file]
和 :wq 类同,其中的保存操作仅当文件已修改时才执行。
'hidden' 置位时,如果还有其他窗口,保存文件后会隐藏当
前缓冲区。
Vim9 脚本不支持本命令,易和常见变量名混淆。
:exi :exit
:[range]exi[t][!] [++opt] [file]
同 :xit 。
ZZ
ZZ 仅当文件已修改时保存当前文件。然后关闭当前窗口 (同
:x )。
当前文件同时在多个窗口中显示时,只关闭当前窗口。
ZQ
ZQ 直接丢弃当前窗口的所有修改并退出 (同 :q! )。
多 窗 口 和 缓 冲 区 全 局 退 出 window-exit
:qa :qall
:qa[ll] 整体退出 Vim,如果存在任何已修改的缓冲区,本命令会失败 (可用
:bmod 跳转到下个已修改的缓冲区)。但 'autowriteall' 置位时,
会自动保存全部修改后退出 Vim,同 :wqall 。
:conf[irm] qa[ll]
退出 Vim。如果存在任何已修改的缓冲区,会提示确认。
见 :confirm 。
:qa[ll]! 强制退出 Vim,丢弃所有缓冲区全部修改。
另见 :cquit ,功能相同但退出时返回非零退出码。
:quita :quitall
:quita[ll][!] 同 :qall 。
:wqa[ll] [++opt] :wqa :wqall :xa :xall
:xa[ll] 保存全部修改后退出 Vim。如果有无名缓冲区、只读缓冲区或因其他原
因无法写入的缓冲区,或者有还在运行作业的终端,本命令会失败。
:conf[irm] wqa[ll] [++opt]
:conf[irm] xa[ll]
保存全部修改后退出 Vim。如果有只读缓冲区或因其他原因无法写入的
缓冲区,会提示确认。见 :confirm 。
:wqa[ll]! [++opt]
:xa[ll]! 保存全部已修改缓冲区,包括只读缓冲区,然后退出 Vim。如果有无名
缓冲区或因其他原因无法写入的缓冲区,或者有还在运行作业的终端,
本命令仍然会失败。
:confirm :conf
:conf[irm] {command} 执行 {command},遇到需要确认的操作时,弹出对话框。可用
于 :q 、 :qa (退出确认)、 :w 命令 (覆盖只读文件确
认) 以及其他可能因类似原因失败的命令,如 :only 、
:buffer 、 :bdelete 等。
示例:
:confirm w foo
"foo" 存在时,提示确认。
:confirm q
缓冲区已修改时,提示确认。
:confirm qa
对每个已修改缓冲区逐个提示: 是 (保存)、否 (丢弃)、全部保存或全部丢弃。
如果希望缺省所有操作都带确认,可置位 'confirm' 选项。
:browse :bro E338
:bro[wse] {command} 为 {command} 参数弹出文件选择对话框。目前支持命令有:
:e 、 :w 、 :wall 、 :wq 、 :wqall 、 :x 、 :xall 、
:exit 、 :view 、 :sview 、 :r 、 :saveas 、 :sp 、
:mkexrc 、 :mkvimrc 、 :mksession 、 :mkview 、
:split 、 :vsplit 、 :tabe 、 :tabnew 、 :cfile 、
:cgetfile 、 :caddfile 、 :lfile 、 :lgetfile 、
:laddfile 、 :diffsplit 、 :diffpatch 、 :open 、
:pedit 、 :redir 、 :source 、 :update 、 :visual 、
:vsplit 以及 :qall (需要置位 'confirm')。
{仅对 Win32、Motif、GTK 和 Mac GUI 有效;
控制台模式下,如果存在 FileExplorer 自动命令组,
`browse edit` 也可用}
如果当前环境不支持浏览,会报错。如果编译时未加入
+browse 特性、或 {command} 不支持浏览,直接执行
{command},不弹窗。
`:browse set` 同 :options 。
关于 `:browse oldfiles`,另见 :oldfiles 。
示例用法:
:browse e $vim/foo
在 $vim/foo 目录里打开文件浏览器,编辑选中的文件。
:browse e
在 'browsedir' 指定目录里打开浏览器,编辑选中的文件。
:browse w
在当前缓冲区所在目录里打开浏览器,以当前缓冲区文件名作为缺省。
将缓冲区保存到选中文件。
:browse w C:/bar
在 C:/bar 目录里打开浏览器,以当前缓冲区文件名作为缺省,将缓冲
区保存到选中文件。
另见 'browsedir' 选项。
在不支持浏览功能的 Vim 版本中,会照原样执行命令,不作任何修改。
browsefilter
在 MS-Windows 和 GTK 上,可自定义浏览对话框中使用的文件过滤器 (filter)。通过设
置 g:browsefilter 或 b:browsefilter 变量,可以修改全局或缓冲区局部的过滤规
则。变量中可包含多个过滤器,每个过滤器格式为:
"{过滤器标签}\t{pattern};{pattern}\n",其中 {过滤器标签} 是显示在 "文件类型"
组合框里中的文本,而 {pattern} 模式用于过滤文件名。多个模式之间以 ";" 分隔。
Motif 上也使用相同格式,但实际只使用首个模式 (因为 Motif 只支持一个模式,但用
户可以手动编辑)。
例如,要在对话框中只显示 Vim 文件,可用以下命令:
let g:browsefilter = "Vim scripts\t*.vim\nVim Startup Files\t*vimrc\n"
还可以通过设置 b:browsefilter 变量,为单个缓冲区覆盖全局过滤规则。通常会在文
件类型插件里设置该变量,使浏览对话框根据当前编辑文件类型显示相关条目。缺点是这
样不方便打开其他类型的文件。要解决此问题,在 Windows 上添加如下最终过滤器:
All Files\t(*.*)\t*\n
在其他平台上,则可用:
All Files\t(*)\t*\n
这样用户仍然可以访问任意类型文件。
如果希望仅在 Vim 支持 browsefilter 时才进行设置,可用 has("browsefilter") :
if has("browsefilter")
let g:browsefilter = "过滤规则"
endif
可用 :cd 、 :tcd 和 :lcd 命令换切换工作目录 (即当前目录),无需在文件名前重
复书写完整目录路径。工作目录的切换同样也影响外部命令的执行,例见 :!ls 。
'cpoptions' 里包含 '.' 标志位且当前缓冲区被修改时,无法切换目录,除非使用的目
录切换命令加上 "!" 强制执行。
:cd E747 E472
:cd[!] 在非 Unix 系统上且 'cdhome' 关闭时: 显示工作目录名。
否则,将全局工作目录切换到用户主 (home) 目录。清除窗口
局部目录。
在所有的系统上,可用 :pwd 统一查看工作目录。
:cd[!] {path} 将全局工作目录切换到 {path}。{path} 为相对路径时,会依
据 'cdpath' 列出的目录进行搜索。
清除窗口局部工作目录。
已打开文件的路径不受影响,因为系统会记录其完整路径。但
参数列表 ( arglist ) 里的文件路径可能受影响!
MS-Windows 上,会同步切换当前驱动器。
要切换到当前文件所在目录:
:cd %:h
:cd- E186
:cd[!] - 回退到上次执行 ":cd {path}" 命令之前的全局工作目录。
:chd :chdir
:chd[ir][!] [path] 同 :cd 。
:tc :tcd
:tc[d][!] {path} 和 :cd 类似,但设置当前标签页的局部工作目录。当前窗
口也会同步使用该目录。其他标签页窗口、当前标签页内有自
己窗口局部目录的窗口都不受影响。
:tcd-
:tc[d][!] - 回退到上次执行 ":tcd {path}" 命令之前的标签页局部工作
目录。
:tch :tchdir
:tch[dir][!] 同 :tcd 。
:lc :lcd
:lc[d][!] {path} 和 :cd 类似,但设置当前窗口的局部工作目录。其他窗口
不受影响,切换窗口后会停止使用 {path} 作为工作目录。
:lcd-
:lc[d][!] - 回退到上次执行 ":lcd {path}" 命令之前的窗口局部工作目
录。
:lch :lchdir
:lch[dir][!] 同 :lcd 。
:pw :pwd E187
:pw[d] 显示当前生效的工作目录名。
另见 getcwd() 。
:pwd-verbose
'verbose' 非零时, :pwd 也会显示当前工作目录的生效作
用域。例如:
" 由 :cd 设置全局工作目录
:verbose pwd
[global] /path/to/current
" 由 :lcd 设置窗口局部工作目录
:verbose pwd
[window] /path/to/current
" 由 :tcd 设置标签页局部工作目录
:verbose pwd
[tabpage] /path/to/current
只要从未执行过 :lcd 或 :tcd 命令,所有窗口都共享同一个全局目录。窗口切换命
令不会改变工作目录。
执行过 :lcd 命令后,当前窗口会独立使用指定目录。未通过 :lcd 设置窗口局部目
录的窗口,会继续沿用全局或标签页局部目录。切换窗口时,工作目录会自动切换为目标
窗口的局部目录。如未设置,则沿用全局或标签页局部目录。新建窗口时,会继承当前窗
口的局部目录 (如有)。
执行过 :tcd 命令后,当前标签页内缺省使用指定目录,当前窗口会丢失窗口局部目
录并直接使用标签页局部目录。其他标签页目录不受影响。跳转到其他标签页时,工作目
录会自动切换为目标标签页的局部目录。如未设置,则沿用全局目录。
执行过 :cd 命令后,当前窗口及当前标签页会丢失其局部目录,直接共享全局目录。
用过 :cd 后,文件读写操作都会基于全局目录的完整路径。部分网络文件系统上可能
出现兼容性问题。使用完整路径名的好处是已打开文件会锁定原始完整路径,不受目录切
换影响。例如: 假定存在 "a:test" 文件和 "a:vim" 目录。依次执行命令: `:e test`、
`:cd vim 、 :w` 时仍会覆盖原文件 "a:test",而非 "a:vim/test"。但此时执行
`:w test` 会另存到文件 "a:vim/test",因为这时 "test" 指向的文件名和 :cd 之前
发生了变化。
尽管 Vim 专为编辑文本文件设计,但也可用于编辑二进制文件。使用 Vim 的 -b 参数
(b 代表二进制 (binary)) 可使 Vim 以二进制模式执行文件读写操作,并自动设置二进
制文件编辑的相关选项 (打开 'binary','textwidth' 设为 0,关闭 'modeline',关闭
'expandtab')。手动打开 'binary' 选项的效果相同。但务必在读取文件前完成操作。
编辑二进制文件时,要注意以下要点:
- 编辑可执行文件时,不要改变文件总字节数。仅可使用 R 或 r 命令修改内容。禁
止使用 x 或退格键删除字符。
- 将 'textwidth' 选项设为 0。否则行会被意外拆分为两行。
- 如果文件中 <EOL> (行尾结束符) 数量很少,会出现超长单行。如果需要编辑屏幕显示
不下的行,可复位 'wrap' 选项,启用横向滚动。如果一行过长 (Amiga 上限超过
32767 个字节,32 位或 64 位系统上限更高,见 limits ),该行无法正常编辑。文
件读取时长行会被自动拆分,也可能触发 "内存不足" 错误。
- 确保在读取文件 前 置位 'binary' 选项。不然,<CR><NL> 和 <NL> 都被认为行尾结
束符,写回文件时会自动将 <NL> 替换为 <CR><NL>,破坏二进制结构。
- <Nul> 空字符会在屏幕上显示为 ^@。可用 "CTRL-V CTRL-@" 或 "CTRL-V 000" 输入。
- 在文件中插入 <NL> 字符会拆分一行。文件保存时,会将 <EOL> 转换为 <NL> 写入。
- Vim 缺省会在无 <EOL> 的文件末尾自动追加 <EOL>。打开 'binary' 选项会禁用这一
行为。如果需要手动添加文件末尾的 <EOL>,可打开 'endofline' 选项。通过查阅该
选项值,可判断文末尾是否有 <EOL> (无法直接通过文本本身判断)。
Vim 支持对文件进行加密写入与解密读取。加密文本没有正确密钥无法读取。
{仅当编译时加入 +cryptv 功能才有效} E833
交换文件与撤销文件中的文本也会被加密。 E843
不过,加密是分块进行的,这可能缩短密钥破解难度。要提高安全性,可关闭交换文件,
但程序崩溃会导致工作内容丢失。关闭撤销文件的负面影响较小。
:set noundofile
:noswapfile edit secrets
注意: 内存中的文本不加密。系统管理员在用户编辑时理论上可查看文本内容。
:!filter 或 `:w !command` 过滤的文本也不经加密。'viminfo' 文件同样不会加密。
这些都可能造成文本泄露。
要编辑高度机密的文本:
:set noundofile viminfo=
:noswapfile edit secrets.txt
牢记禁用交换文件后,发生系统崩溃或停电等事件时,会有丢失全部工作成果的风险。
_警告_: 如果输入密钥时出错,随后保存并退出,文本内容将永远丢失,无法恢复!
要使用加密功能,常规方法是用 :X 命令,该命令会提示用户输入密钥。后续保存命令
会使用该密钥加密文件。再次编辑该文件时,Vim 会提示输入密钥。输入正确密钥后,即
可正常读取文本。否则,文本会显示为乱码。
:X
:X 提示输入加密密钥。输入时不会显示明文。防止他人通过屏幕窥视。
输入密钥会保存在 'key' 选项里,文件保存时使用该密钥加密。
直到执行保存操作前,文件保持不变。注意 :xit 和 ZZ 等命令仅在文件有
其他实际修改时才 会 保存文件并加密。
另见 -x 。
文件保存时,检查 'key' 选项值。非空时,写入的文件会以该值作为密钥进行加密。文
件头部会添加魔术标识,使于 Vim 识别该文件为加密文件。
要停止加密,可将 'key' 选项复位为空值:
:set key=
可通过 'cryptmethod' 选项选择加密算法。可选值为:
:setlocal cm=zip " 弱加密算法,后向兼容
:setlocal cm=blowfish " 存在安全漏洞,不建议使用
:setlocal cm=blowfish2 " 中等强度加密算法
:setlocal cm=xchacha20v2 " 基于 libsodium 的中等强度加密算法
请在文件保存前完成加密算法设置。读取加密文件时,会自动设置文件写入时选择的加密
算法。只要在保存前完成,可重新修改 'cryptmethod' 切换不同算法。
要设置用于新建文件的缺省加密算法,可在 vimrc 文件中放入:
set cm=blowfish2
强烈推荐使用 "blowfish2"。仅当必须使用不支持该算法的旧版 Vim 时,再选择其他算
法。
文件读写时的提示信息会显示加密算法,zip 算法显示 "[已加密]",其他算法则显示
"[{算法名}]",如 blowfish 算法显示 "[blowfish]",以此类推。
写入撤销文件时,会使用与文本文件相同的密钥与加密算法。 persistent-undo 。
可通过以下条件判断是否提供 blowfish 支持:
has('crypt-blowfish')
has('crypt-blowfish2')
尽管更早时就引入 blowfish 支持,此测试只可用于 Vim 7.4.1099 及以后版本。因此该
条件失败并不代表不支持 blowfish。以下方式判断会更准确:
v:version >= 703
判断 blowfish2 支持可用:
v:version > 704 || (v:version == 704 && has('patch401'))
如果确定当前 Vim 已包含 7.4.237 补丁,可简化判断:
has('patch-7.4.401')
E817 E818 E819 E820
如果加密过程异常,可能导致文件保存后无法解密读取。因此,Vim 会自动执行加密有效
性校验。如果出现以上任一错误码,切勿继续以加密方式保存文件!要修复问题,可能需
要重新编译 Vim。
E831 内部错误,理论上"不应该发生"。如果能复现该错误,请向开发者报告。
读取加密文件时,如果 'key' 选项非空,会被用作解密密钥。否则,会提示输入密钥。
如果跳过密钥输入或者密钥不符,会以未解密状态打开文件。密钥不符不会产生警告 (该
设计可增加暴力破解密钥难度)。
如要读取使用不同密钥加密的文件,先将 'key' 选项清空,然后 Vim 就会提示输入新密
钥。不要使用 :set 命令手动输入密钥,容易被他人窥视。
'key' 选项值属于机密信息,永远无法被察看。切勿在 vimrc 文件里直接设置该选项。
可通过系统 "file" 命令识别 Vim 加密文件,为此,可在系统 "magic" 文件 (通常位于
"/etc/magic"、"/usr/share/misc/magic" 或其他系统支持路径) 里加入以下内容:
0 string VimCrypt~ Vim encrypted file
>9 string 01 - "zip" cryptmethod
>9 string 02 - "blowfish" cryptmethod
>9 string 03 - "blowfish2" cryptmethod
注意:
- 使用 'charconvert' 进行编辑转换时,无法实施加密。
- 复制或删除的文本会存入编号寄存器。寄存器内容可能被保存到 .viminfo 文件,存在
被读取的风险。建议修改 'viminfo' 选项配置。
- 如果暂时离开,他人可能在 Vim 里输入命令窃取信息,但对方仍然无法获取密钥。
- 输入密钥时如果发生错误,可能导致文本无法恢复!
- 如果通过 ":set key=value" 命令输入密钥,该命令会保存在历史记录,从而会使
'key' 值暴露在 viminfo 文件里。
- 不存在绝对的 100% 安全。Vim 使用的加密算法未经过安全性强度测试。
- 'cryptmethod' 是 "zip" 加密算法已知可以破解。4 字符密钥约 1 小时可破解,6 字
符密钥约 1 天可破解 (在 Pentinum 133 PC 上实测)。前提是知晓文件中的部分已知
明文。专家可破解任意密钥,文本解密后,密钥也可被推算出,使用同一密钥加密的其
他文件均可被破解。
- Pkzip 所用加密算法和 'cryptmethod' 的 "zip" 算法一致,美国政府对其出口不持异
议。Pkzip 公开文件 APPNOTE.TXT 详细描述了该算法的原理。
- 'cryptmethod' 的 "blowfish" 实现有漏洞。攻击者可以破解文件前 64 字节内容,部
分情景下可破解更多内容。因此,不推荐该算法,但它仍是 Vim 7.3 和 7.4 版本支持
的最强加密算法。"zip" 算法安全性更低。
- Vim 起源于荷兰。源代码由荷兰发布。因此,加密相关代码不涉及美国出口管制。
Vim 会记录文件开始编辑时的修改时间戳、权限和文件大小。用于避免在用户不知情时,
同一个文件同时出现两个不同版本。
执行外壳命令 ( :!cmd suspend :read! K ) 后,Vim 会对窗口里的所有缓冲区的
修改时间戳、权限和文件大小进行比较。检测到任何文件已被外部修改时,会触发其关联
的 FileChangedShell 自动命令,或直接显示警告。在 GUI 中,该检测也会在 Vim 重
新获得输入焦点时发生。
E321 E462
如果希望文件被外部被修改时自动重新加载,可置位 'autoread' 选项。但如果在 Vim
内该文件已修改,此功能不会生效。
ignore-timestamp
如果既不想被警告,也不想自动重新加载,可用:
set buftype=nofile
或者,从终端启动 gvim 时直接指定:
gvim file.log -c "set buftype=nofile"
注意 定义 FileChangedShell 自动命令后,不会显示警告信息或提示。该自动命令应负
责处理相关逻辑。
目录 (例如通过 netrw-browse 打开) 不会触发修改警告,但如果开始编辑一个尚不存
在的新文件,而在外部创建了同名目录,仍会收到警告。
当 Vim 注意到文件的时间戳已变更,但缓冲区本身未被修改时,会进一步校验文件内容
是否一致,这是通过重新读取文件 (到临时隐藏缓冲区,用后立即删除),并对比文本完
成的。文本相同时,不显示警告。
如果觉得检测不够及时,可用以下命令手动触发检测。
:checkt :checktime
:checkt[ime] 手动检查所有缓冲区对应的文件量否在 Vim 外部被修改。该
命令检查并提醒用户同一文件出现两个不同版本。
如果通过自动命令、 :global 命令调用或其他非手动输入方
式执行,实际检查会被推迟到重新加载文件无副作用的安全时
机再执行。
每个已加载的缓冲区会检查对应的文件是否被修改。如果是,
会采取以下行动。如果缓冲区未修改且 'autoread' 置位,自
动重新加载。否则,提示用户选择是否重新加载。如果文件被
删除,会报错。如果文件原本不存在但现已创建,会显示警
告。
文件完成一次检查后,时间戳被重置。从而不会被重复提醒。
重新加载时,语法高亮、位置标记、比较结果以及
'fileencoding'、'fileformat' 和 'binary' 选项均保持不
变。如果需要同步更新这些设置,可通过 v:fcs_choice 实
现 (例如代码排版工具修改了文件)。
:[N]checkt[ime] {filename}
:[N]checkt[ime] [N]
对指定缓冲区进行时间戳检查。可通过文件名、缓冲区编号
或者匹配模式指定缓冲区。
E813 E814
Vim 会在用户确认后重新加载缓冲区。如果该缓冲区位于可见窗口,重载操作在该窗口的
上下文中进行。否则,会使用一个特殊窗口 (译者注: 错误信息中称为自动命令窗口) 重
载,确保大多数自动命令可以正常工作。此窗口无法被关闭,还有少量其他限制。因此,
最好确保所有操作只涉及当前缓冲区。例如,设置窗口局部选项可能会选错窗口。分割窗
口、在其中执行操作后再关闭新窗口通常是安全的 (假定没有其他自动命令带来的副作
用)。关闭不相关的窗口和缓冲区则会引发问题。
写入文件前,会先检查时间戳。如果发生了变更,Vim 会提示确认是否覆盖文件:
警告: 此文件自读入后已发生变动!!!
确实要写入吗 (y/n)?
按 'y' 则写入继续。按 'n' 则中止写入操作,如果用的是 :wq 或 ZZ 命令,此时
Vim 不会退出,再给用户一次写入文件的机会。
该警告通常表示在编辑会话开始后,文件已被外部修改。这可能来自其他用户,此时建议
将文件另存为新文件,对比差异 (可用 "diff" 程序),确认是否需要合并双方的修改。
当然也有可能用户自己在另外一个编辑会话中或通过其他命令 (如过滤命令) 修改了该文
件。此时可自主决定哪个版本需要保留。
时间戳检查精度取决于文件系统。Unix 上通常支持亚秒级。老旧文件系统和 MS-Windows
系统通常支持秒级。可用 `has('nanotime')` 判断是否支持亚秒级时间戳检查。
有一种特殊情况会收到警告但其实无害: Win32 系统上,夏令时开始的当天可能会出现问
题。Win32 库的某些机制会导致 Vim 对一小时的时差出现误判。次日问题会自动消失。
文件搜索机制目前适用于 'path'、'cdpath' 和 'tags' 选项、以及 finddir() 和
findfile() 函数。其他命令则使用 wildcards 机制,略有不同。
文件搜索分为三种不同类型:
1) 向下递归搜索: starstar
向下搜索使用通配符 '*'、'**' 以及操作系统支持的其他通配符。'*' 和 '**' 由
Vim 内部处理,全平台通用。注意 "**" 仅在路径组件开头出现时才会作为特殊通配
符处理。
'*' 的用法很简单: 匹配 0 个或任意多个字符。等价于正则模式的 ".*"。但注意文
件搜索不使用 "." 元字符。
'**' 则复杂得多:
- 仅 匹配目录,不匹配文件。
- 缺省最多递归匹配 30 层子目录。可遍历整个目录树。
- 也可通过在 '**' 后追加数值来自定义最大递归层数。
例如,'/usr/**2' 可匹配:
/usr
/usr/include
/usr/include/sys
/usr/include/g++
/usr/lib
/usr/lib/X11
....
但 不会 匹配 '/usr/include/g++/std',因为这已经是第三层目录。
合法的层数上限值为 0 ('**0' 会被移除) 到 100。如果小于 0,缺省 30
层。如果大于 100,按 100 层处理。系统本身还存在路径长度上限,通常为
256 或 1024 字节。
- '**' 只能放在路径末尾、后接路径分隔符,或后接层数上限值加路径分隔符。
可以按任何顺序混合使用 '*' 和 '**':
/usr/*/sys/**
/usr/*tory/sys/**
/usr/**2/sys/*
2) 向上递归搜索:
指定一个起始目录,向上遍历目录树搜索文件。可选给出若干终止目录,限制搜索范
围。终止目录通过 ';' 追加到路径 (对 'path' 选项) 或文件名 (对 'tags' 选项)
后,多个终止目录以 ';' 分隔。仅写 ';' 不指定终止目录,代表一直向上搜索到根
目录。
/usr/include/sys;/usr
会按以下顺序搜索:
/usr/include/sys
/usr/include
/usr
使用相对路径时,起始目录是 Vim 的当前目录,但当相对路径以 './' 开头时,使用
当前文件所在目录 (用于 'tags' 选项且 'cpoptions' 里包含 'd' ( cpo-d ) 时例
外,此时还是使用当前目录)。相对路径则用作固定部分。从起始目录开始向上遍历,
实际搜索路径为每一层目录加上固定部分。
假定 Vim 当前目录为 /u/user_x/work/release,然后设置
:set path=include;/u/user_x
使用 gf 搜索文件时,搜索路径依次是 (固定部分是 "include"):
/u/user_x/work/release/include
/u/user_x/work/include
/u/user_x/include
注意: 如果 'path' 包含了不存在的目录,Vim 会直接跳过该目录,向上搜索也不会
搜索该目录的上层目录。
3) 上下混合搜索
假定 Vim 当前目录为 /u/user_x/work/release,然后设置
set path=**;/u/user_x
使用 gf 搜索文件时,搜索路径依次是:
/u/user_x/work/release/**
/u/user_x/work/**
/u/user_x/**
要小心 !这种写法可能重复搜索,非常耗时,因为 "/u/user_x/**" 已包含
"/u/user_x/work/**" 和 "/u/user_x/work/release/**"。结果是
"/u/user_x/work/release/**" 会被搜索三遍,而 "/u/user_x/work/**" 会被搜索两
遍。
推荐改用以下写法:
:set path=**,/u/user_x/**
搜索路径变为:
/u/user_x/work/release/**
/u/user_x/**
这会搜索相同的目录,但搜索顺序不同。
注意 :find 、 :sfind 和 :tabfind 命令的补全功能目前暂不支持 'path' 里包
含 URL、使用带层数限定的双星通配符 (/usr/**2) 或向上搜索 (;) 记法的项目。
vim:tw=78:ts=8:noet:ft=help:norl: