80

The title is very descriptive. Just in case, I will give an example:

START BLOCK1
something
END BLOCK1

START BLOCK2
something
somenthing...
END BLOCK2
  1. I select the BLOCK1 in visual mode
  2. I yank it by pressing y
  3. How can I save the yanked BLOCK1 to some other file?
Keith Pinson
  • 7,835
  • 7
  • 61
  • 104
Léo Léopold Hertz 준영
  • 134,464
  • 179
  • 445
  • 697

8 Answers8

146

Select the text you wish to save, in either line visual or block visual mode, and

:w new.txt

That's what you type, but you won't actually see exactly what's above. When you press :, you'll go to the command line which will automatically get filled in with selection information. It'll look something like this:

:'<,'>

Just carry on typing the rest (w new.txt) to get

:'<,'>w new.txt

...and press enter.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Rook
  • 60,248
  • 49
  • 165
  • 242
  • 19
    That doesn't provide the expected result as it only writes full lines, disregarding the selection start and end position inside the line. Any solution for that? Otherwise I like to file the main question again. – dronus Nov 08 '12 at 14:41
  • 2
    @dronus - I don't quite understand what you're asking. This does what the OP asked, to the best of my understanding the question. – Rook Nov 10 '12 at 20:21
  • 7
    If you select in any non-line visual mode, `:w` still writes out full lines touched by the selected range, but not the exact range beginning or ending inside of lines. For example, if you select a narrow column in block select mode, or a part of one line in visual select mode, the full line will be written by `:w`, even if `y`would copy the correct parts of the line. – dronus Nov 11 '12 at 22:12
  • 1
    @dronus - Ah, okey. Yes, that's correct. But still, while I can't talk for others, what it does is *expected* behaviour for me. – Rook Nov 12 '12 at 15:11
18

With the block is selected, you can :'<,'>w other-file, which will write only the selected block to other-file. Hitting : in visual mode should place '<,'> into the command line for you already, so you really only have to type :w other-file.

ephemient
  • 198,619
  • 38
  • 280
  • 391
  • 3
    Vim always selects whole lines for piping to external command, so you can use the unix/cygwin 'cut' command to select rectangle of column N to M, of each line in the selection: `:'<,'>w !cut -cN-M > new.txt`. Surprised that highest voted answer and readers don't seem to understand the question. – mosh Nov 22 '16 at 14:20
  • @mosh but when the selected text is not aligned to a column, this would not work either. – Sajuuk Aug 21 '21 at 12:50
7

There's probably a simpler way to do this, but what I would do is create a new buffer (or tab) and then paste it in with p. You can create a new buffer with :new or a new tab with :tabnew. You can write the buffer/tab to a file as normal with :w filename.

rmeador
  • 25,504
  • 18
  • 62
  • 103
3

Like @dronus mentioned in the comments, the :w !pbcopy suggestions does not copy correctly because it copies the entire line. If I want to copy only the url in a line, I will not be able to. Here's a line that you can add to your .vimrc file so that everytime you hit CTRL-C, the selected line in your vim will be copied to clipboard:

map <C-c> y:e ~/clipsongzboard<CR>P:w !pbcopy<CR><CR>:bdelete!<CR>

If you'd like to read details about what this does, you can read about this on my blog

Its the same implementation as what @rmeador suggested.

songz
  • 2,082
  • 1
  • 14
  • 18
3

Similar to @songz's solution, I prefer do it like this using ":new"

vmap <C-c> y:new ~/.vimbuf<CR>VGp:x<CR>:!pbcopy < ~/.vimbuf<CR><CR>
chenkaie
  • 549
  • 3
  • 7
  • pbcopy is, to my knowledge, only present on OSX. There are similar programs on Linux and other systems but they go by different names and work differently. – Josh Rumbut Jul 27 '15 at 20:13
  • Yep, it works only if pbcopy executable :) So no harm at all – chenkaie Jul 29 '15 at 16:36
1

Vim get the visual selection and save to a file:

    function! Get_visual_selection()
        "get the position of left start visual selection
        let [line_start, column_start] = getpos("'<")[1:2]
        "get the position of right end visual selection
        let [line_end, column_end] = getpos("'>")[1:2]
        "gotta catch them all.
        let lines = getline(line_start, line_end)
        if len(lines) == 0
            return ''
        endif
        "edge cases and cleanup.
        let lines[-1] = lines[-1][: column_end - 2]
        let lines[0] = lines[0][column_start - 1:]
        return join(lines, "\n")
    endfunction

    function Save_visually_selected_text_to_file()
        let selected_text = Get_visual_selection()
        call writefile(split(selected_text, "\n"), "/tmp/something.txt")
    endfunction

    "the c-u does a union of all lines in visual selection.
    "this goes in the vimrc
    vnoremap <F10> :<c-u>call Save_visually_selected_text_to_file()<cr>
darc
  • 530
  • 4
  • 15
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
0

Basing on @chenkaie's variant, works well for me:

let mapleader = "," let g:mapleader = "," vmap <leader>y y:new ~/.vbuf<CR>VGp:x<CR> nmap <leader>p :r ~/.vbuf<CR>

Jaime Asm
  • 131
  • 4
  • 11
0

In addition to selected answer above,

  • when using the mouse to select (1),

  • and the problem of only copying whole lines mentioned by the comment of @dronus to it, when just wanted to partly copy lines (2):

(1) At my Debian based DietPi (Raspberry PI)system, vim acts a little different like in the preferred solution above when using the mouse to enter and select 'VISUAL MODE' on my Ubuntu 16.04 work station. Then

  • y to yank it

but if I type ':' for command, it will not show up with the

'<,'>

where I can just simply add my

w new.txt

after it. So I just typed it by myself and it did work:

'<,'>w new.txt

and it copies the whole line(s) yanked content to my file 'new.txt', whereas '<,' seem to mean 'copy selected lines and '>' redirect it to the write command's referenced file.

(2) And to the problem of not pasting part of the line(s), like in @dronus comment mentioned, this solution (the selected one, first alternative) worked for me:

Edit the first file, yanking the text you want. Then open your second file from within vi (:e /path/to/other/file) and paste it (by typing p). Save it (like above ':w new.txt'.

It will then just copy the part of the lines marked up by mouse or 'y' with the cursors.

[EDIT] On my Ubuntu system: Sometimes selecting by mouse does NOT enter 'VISUAL MODE' in vim. Then the normal copy/paste can be selected using the context menu... I have not found the reason why Ubuntu changed it behaviour from a 'client acting behaviour' to a 'host' one (withUbuntu hosting the ssh bash window to my 'Client')...

pedda
  • 106
  • 7