Thursday, December 18, 2014

Re: How to use bufdo?

On 2014-12-18 11:26, Ven Tadipatri wrote:
> So I just learned about a cool new command called 'bufdo' where you
> can execute a command across multiple buffers. Unfortunately, I
> can't quite get it to work.

The multi-file prefixes ("bufdo" along with its cousins "windo",
"tabdo", and "argdo") are great tools to have in your tool-belt.

> I've got 2 buffers open side by side (this is output I've piped to
> vi, so it's not saved in any file) and I want to grep for
> "somestring" in both.
>
> :bufdo !grep somestring
>
> It breaks out of vi with a message
> "[No write since last change]"

I think the problem you're seeing is that you're shelling out to the
grep command but not specifying a filename, so for each buffer in
your buffer-list, it's running grep, then waiting for input on stdin.

To answer your immediate question, you want to pass the filename to
grep which can be done via the shortcut "%" (":help :_%")

:bufdo !grep somestring %

This does search of the file on-disk (and relies on the existence of
an external grep command which you may not have on Win32, so you'd
have to use FINDSTR.EXE or FIND.EXE there) rather than the buffer in
Vim, which matters if any files are modified but not saved. If you
want to effectively grep all the buffers, even if they're unsaved,
you can use

:bufdo g/somestring

which prints them by default (thus the name "grep", comes from
":g/re/p", where "re" is a regular expression, and "p" is the
default command, to print the matching line), or you can use

:bufdo g/somestring/#

which I find more helpful, to get the matching line-numbers.

> I tried playing around with these:
> :set autowriteall
> :set hidden
>
> But that didn't work either...so how do a simple grep across buffers
> without having to save?

Because the :{buf,arg,win,tab}do commands leave the current buffer,
you either have to write the file (whether via 'autowriteall' which
makes me nervous, or manually issuing a write as part of your
command) or tell vim that it's okay to leave the buffer as done by
the 'hidden' setting. I tend to use the 'hidden' route.
Alternatively, if your command is read-only (as yours is) you can open
a new window and then issue the command there:

:new
:bufdo ...

If you want to write the modified file, you can do so as part of the
command, something like


:bufdo %s/foo/bar/g|w

will go through all the buffers, substituting "foo" to "bar" then
writing the file. I rarely do (even after using vim for more than
a decade) this because it's easy to make a mistake that is hard to
recover from. I much prefer to do

:set hidden
:bufdo %s/foo/bar/g

then, after reviewing all my changes and confirming they're what I
want, I then issue

:wa

to write all the unsaved files.

Hope this helps explain what's going on, and brings another tool into
your arsenal.

-tim





--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments: