How to delete multiple buffers in Vim?
Assuming I have multiple files opened as buffers in Vim. The files have *.cpp
, *.h
and some are *.xml
. I want to cl开发者_Go百科ose all the XML files with :bd *.xml
. However, Vim does not allow this (E93: More than one match...).
Is there any way to do this?
P.S. I know that :bd file1 file2 file3
works. So can I somehow evaluate *.xml
to file1.xml file2.xml file3.xml
?
You can use <C-a>
to complete all matches. So if you type :bd *.xml
and then hit <C-a>
, vim will complete the command to :bd file1.xml file2.xml file3.xml
.
:3,5bd[elete]
Will delete buffer range from 3 to 5 .
You also can use alternatively use:
:.,$-bd[elete] " to delete buffers from the current one to last but one
:%bd[elete] " to delete all buffers
You can use this.
:exe 'bd '. join(filter(map(copy(range(1, bufnr('$'))), 'bufname(v:val)'), 'v:val =~ "\.xml$"'), ' ')
It should be quite easy to add it to a command.
function! s:BDExt(ext)
let buffers = filter(range(1, bufnr('$')), 'buflisted(v:val) && bufname(v:val) =~ "\.'.a:ext.'$"')
if empty(buffers) |throw "no *.".a:ext." buffer" | endif
exe 'bd '.join(buffers, ' ')
endfunction
command! -nargs=1 BDExt :call s:BDExt(<f-args>)
Try the script below. The example is for "txt", change it as needed, e.g. to "xml". Modified buffers are not deleted. Press \bd to delete the buffers.
map <Leader>bd :bufdo call <SID>DeleteBufferByExtension("txt")
function! <SID>DeleteBufferByExtension(strExt)
if (matchstr(bufname("%"), ".".a:strExt."$") == ".".a:strExt )
if (! &modified)
bd
endif
endif
endfunction
[Edit] Same without :bufdo (as requested by Luc Hermitte, see comment below)
map <Leader>bd :call <SID>DeleteBufferByExtension("txt")
function! <SID>DeleteBufferByExtension(strExt)
let s:bufNr = bufnr("$")
while s:bufNr > 0
if buflisted(s:bufNr)
if (matchstr(bufname(s:bufNr), ".".a:strExt."$") == ".".a:strExt )
if getbufvar(s:bufNr, '&modified') == 0
execute "bd ".s:bufNr
endif
endif
endif
let s:bufNr = s:bufNr-1
endwhile
endfunction
I too had a need for this functionality all the time. This is the solution I have in my vimrc.
function! GetBufferList()
return filter(range(1,bufnr('$')), 'buflisted(v:val)')
endfunction
function! GetMatchingBuffers(pattern)
return filter(GetBufferList(), 'bufname(v:val) =~ a:pattern')
endfunction
function! WipeMatchingBuffers(pattern)
let l:matchList = GetMatchingBuffers(a:pattern)
let l:count = len(l:matchList)
if l:count < 1
echo 'No buffers found matching pattern ' . a:pattern
return
endif
if l:count == 1
let l:suffix = ''
else
let l:suffix = 's'
endif
exec 'bw ' . join(l:matchList, ' ')
echo 'Wiped ' . l:count . ' buffer' . l:suffix . '.'
endfunction
command! -nargs=1 BW call WipeMatchingBuffers('<args>')
Now, I can just do :BW regex
(e.g. :BW \.cpp$
and wipe all matching buffers that have match that pattern in their pathname.
If you want to delete rather than wipe, you can of course replace exec 'bw ' . join(l:matchList, ' ')
with exec 'bd ' . join(l:matchList, ' ')
TAB
will only autocomplete one file for you as of Vim 7.4.282
use<c-a>
to autocomplete all files.
You can just use:
bd filetype
then just use <c-a>
to facilitate the completion of all open files of specified filetype.
for example, you have 1.xml, 2.xml, 3.xml, and 4.xml, you can do:
bd xml
then press <c-a>
vim will autocomplete for you as follow:
bd 1.xml 2.xml 3.xml 4.xml
you can just press enter to complete the command.
if you have made changes in one of the files mentioned above, do remember to do:
bd! xml
Very simply: use the :bd[elete]
command. For example, :bd[elete] buf#1 buf#5 buf#3
will delete the buffers 1, 3, and 5.
精彩评论