3

I have two tabs open, file1.txt and file2.txt, each with different content.

How can I copy the whole content of file1.txt and overwrite file2.txt with it, resulting in both files having the same content.

This is obviously doable with yanking manually, but I figured there's probably a nice combo that does it all in one go.

Edit : Based on Rich's answer, I ended up doing this :

" SplitOverwrite()
" Yanks all content of the current window and pastes it 
" into the adjascent window, overwriting all existing content
function! SplitOverwrite()

    " Yank the whole file content
    %yank

    " Move cursor to the window right
    wincmd w

    " Delete the whole file content
    %delete

    " Puts the text from register O after the current line
    put 0

    " Deletes the first (empty) line of the file
    1delete

    " Save the file
    w

    " Short version
    "%y|winc w|%d|pu0|1d|w

endfunction

nnoremap <leader>so :call SplitOverwrite()<CR>
0

4 Answers 4

2

Try running this unholy ex command in your first tab:

:%y|tabn|%d|pu0|1d

It’s certainly a combo that does it all in one go, but is it nice?

That’s a rhetorical question: it’s clearly not.

Further details

This is a maximally abbreviated version of the following sequence of commands:

  • :%yank: Yank the entire file by using the :yank command with the % range. (See :help cmdline-ranges.)
  • :tabnext: Move to the next tab.
  • :%delete: Delete the entire buffer by passing the % range to the :delete command
  • :put 0: Put the contents of the yank register (See :help "0) after the current line.
  • :1delete: The commands above will leave a blank line at the top of the file. We can remove this by passing a different range to the :delete command. (N.B. A previous — less efficient — version of this answer instead used norm!ggdd to remove this line by using the :normal command to emulate typing ggdd.)

These have been consolidated into a one-liner by using a | character to run multiple commands on a single line. (See :help :bar).

You can view the documentation for each of these commands by inserting them into a :help query. e.g. :help :yank.

9
  • I think after the :put you need to delete the first line Oct 24, 2018 at 20:05
  • I do delete it! (You might need to refresh the page? The original edit left a blank line at the end but I’ve fixed that by making it even uglier.)
    – Rich
    Oct 24, 2018 at 20:05
  • a true, did not see it Oct 24, 2018 at 20:06
  • 1
    @mike23 Sure! Try replacing tabN with wincmd w. I’ll update the answer with some more explanation when I get a minute.
    – Rich
    Oct 27, 2018 at 15:06
  • 2
    @mike23 You might like to watch this video (one of my two all-time favourite Vim videos) for a terrific example of the power/flexibility of ex commands.
    – Rich
    Oct 29, 2018 at 16:33
4

based on @Warren's answer, there are actually two other alternatives

  1. running from the source file: :w !cat > dest_file (note the space between w and !, which runs an external program and uses the content written as stdin)
  2. running from the destination: :%! cat < source_file (this uses filter and the contents of the destination is discarded since the external program redirected its input)
3

From the file1.txt buffer, say :w! file2.txt.

Then either:

  1. In the file2.txt buffer, say :e! to manually reload that buffer with the new content.

  2. Use one of the "autoread" plugins to make Vim do this automatically and reliably: [1] [2]

3
  • 1
    This gives me a E139: File is loaded in another buffer
    – mike23
    Oct 25, 2018 at 18:07
  • @mike23 Use two Vim instances. Oct 25, 2018 at 19:17
  • 2
    how about :w !cat > file2.txt
    – doraemon
    Oct 31, 2018 at 7:36
1

Another version that uses functions more and avoids messing up the registers

function! SplitOverwrite()

    " get the whole file content
    let x = getline(1, '$')

    " Move cursor to the window right
    wincmd w

    " Delete the whole file content to black hole register
    %delete _

    " set the contents
    call setline(1, x)

    " Save the file
    w
endfunction

nnoremap <leader>so :call SplitOverwrite()<CR>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.