Strange behavior with bufdo

All *do commands are equivalent to some snippet:

┌────────┬───────────┐
│ :argdo │ :first    │
│        │ :{cmd}    │
│        │ :next     │
│        │ :{cmd}    │
│        │ ...       │
├────────┼───────────┤
│ :bufdo │ :bfirst   │
│        │ :{cmd}    │
│        │ :bnext    │
│        │ :{cmd}    │
│        │ ...       │
├────────┼───────────┼────────┬───────────┐
│ :cdo   │ :cfirst   │ :ldo   │ :lfirst   │
│        │ :{cmd}    │        │ :{cmd}    │
│        │ :cnext    │        │ :lnext    │
│        │ :{cmd}    │        │ :{cmd}    │
│        │ ...       │        │ ...       │
├────────┼───────────┼────────┼───────────┤
│ :cfdo  │ :cfirst   │ :lfdo  │ :lfirst   │
│        │ :{cmd}    │        │ :{cmd}    │
│        │ :cnfile   │        │ :lnfile   │
│        │ :{cmd}    │        │ :{cmd}    │
│        │ ...       │        │ ...       │
├────────┼───────────┼────────┴───────────┘
│ :tabdo │ :tabfirst │
│        │ :{cmd}    │
│        │ :tabnext  │
│        │ :{cmd}    │
│        │ ...       │
├────────┼───────────┤
│ :windo │ C-w t     │
│        │ :{cmd}    │
│        │ C-w w     │
│        │ :{cmd}    │
│        │ ...       │
└────────┴───────────┘

Notice that in the case of :bufdo, the snippet runs :bnext which changes the buffer currently displayed in your window. If you want to use :bufdo and preserve the current layout, then you'll need to save and restore the current buffer:

:let curbuf = bufnr('')
:bufdo %s/search/replace/ge
:exe 'b ' . curbuf

If you want to use :windo and preserve the focused window, then you'll need to save and restore the current window:

:let curwin = winnr()
:windo %s/search/replace/ge
:exe curwin . 'wincmd w'
/r/vim Thread