480

How should I rename my current file in Vim?

For example:

  • I am editing person.html_erb_spec.rb
  • I would like it renamed to person.haml_spec.rb
  • I would like to continue editing person.haml_spec.rb

How would I go about doing this, elegantly?

23 Answers 23

539

The command is called :saveas, but unfortunately it will not delete your old file, you'll have to do that manually. see :help saveas for more info.

EDIT:

Most vim installations have an integrated file explorer, which you can use for such operations. Try :Explore in command mode (I would actually map that to a function key, it's very handy). You can rename files with R or delete them with D, for example. But pressing <F1> in the explorer will give you a better overview.

14
  • 7
    I don’t think that it is awkward compared to other editors where you normally can’t move a file. Instead you have to go the file manager of your choice, rename the file, and go back to your editor. If you’re lucky you have to quit and restart your editor if it didn’t got the filename change notification. Commented Sep 7, 2011 at 17:43
  • 183
    You might also like :Sex (shorthand for split explore :-) ) Commented Dec 7, 2011 at 3:03
  • 8
    Also, :e will open explore in the current pane. Less exciting than :Sex but more efficient ;).
    – Josh
    Commented Jul 31, 2012 at 2:35
  • 80
    For the intrepid, vertical :Sex is :Vex.
    – hobbes3
    Commented May 20, 2013 at 16:45
  • 9
    @Josh :E works for me, :e it does not work for me. I use :e to edit other file in the same window.
    – omar
    Commented Apr 11, 2014 at 16:48
218

If you use git and already have the tpope's plugin fugitive.vim then simply:

:GRename newname

This will:

  1. Rename your file on disk - in the same directory as the old file.
  2. Rename the file in git repo.
  3. Reload the file into the current buffer.
  4. Preserve undo history.

If your file was not yet added to a git repo then first add it:

:Gwrite

If you'd like to move the file to a new location, use :GMove

:GMove path/to/newfile
6
  • 5
    I sacrificed two goats in honour of this answer! But I have a small problem with it, because you have to type the path from the root of the working tree; and this often gets rather lengthy in any project. Is there a solution to this? Commented Sep 16, 2015 at 13:06
  • 10
    @xxor: as mentioned in Mesco's answer, you can use Ctrl+R % to insert the current filename, which can then be edited.
    – deltab
    Commented Dec 13, 2016 at 15:53
  • 11
    To combine a few comments here: :Gmove requires the relative path for the new filename. A nice way to do this is to type :Gmove <ctrl-r>% which appends the current path/filename.
    – shmup
    Commented May 8, 2018 at 21:32
  • Doesn't work with new files that are not added to git yet.
    – blues
    Commented Jul 30, 2019 at 9:09
  • 1
    @blues That is exactly why at the end of the answer it says: "If your file was not yet added to a git repo then first add it: :Gwrite"
    – ISQ
    Commented Jul 31, 2019 at 18:12
113

I'm doing it with NERDTree plugin:

:NERDTreeFind

then press m

To rename you can choose (m)ove the current node and change file name. Also there are options like delete, copy, move, etc...

3
  • 3
    you know what, that is the main way I rename stuff these days Commented Nov 21, 2012 at 21:09
  • 4
    This one works really well. Definitely recommend it. Commented Jan 16, 2015 at 9:08
  • 1
    Love the idea. This will be my main change file name method now.
    – SLN
    Commented Feb 25, 2019 at 9:26
91

There's a little plugin that lets you do this.

11
  • 3
    :Rename <newfilename> will move a file from its location to the CWD, so make sure you set the CWD first or prefix the new filename with the proper subdirectory. Commented May 14, 2011 at 20:11
  • 10
    This updated version of Rename.vim handles CWD correctly - always saves file in the directory of original one.
    – ku1ik
    Commented Sep 4, 2011 at 17:56
  • 3
    @AaronMahan I've fixed Rename2.vim (disregarding the smarter but more complex DelvarWorld version) to allow for spaces in paths and forked it here: github.com/aehlke/vim-rename3 Feel free to submit pull requests for even smarter functionality!
    – aehlke
    Commented Jul 31, 2013 at 21:40
  • 4
    @Stabledog Microsoft, apparently. Program Files (x86). Any time this directory needs to be worked with it needs to be wrapped in quotes. Which is uh, a lot. Commented Aug 23, 2017 at 11:18
  • 5
    @JackHasaKeyboard: +10. "Program Files (x86)" wins the all-time "Worst Ever Directory Name in an Operating System which Lacks Symlinks." :)
    – Stabledog
    Commented Aug 24, 2017 at 15:06
85
  • Write the file while editing - :w newname - to create a copy.
  • Start editing the new copy - :e#.
  • (Optionally) remove the old copy - :!rm oldname.

On Windows, the optional 3rd step changes a little:

  • (Optionally) remove old Windows copy - :!del oldname.
11
  • 4
    I use this approach all the time, however, the downside is that you lose your undo tree - so you can't undo anything before the :e
    – rampion
    Commented Jul 30, 2009 at 13:07
  • 7
    Nice. Apparently Ctrl-6 does the same as :e# Commented Jul 31, 2009 at 14:37
  • 50
    The more straightforward way imho is 1) rename the current buffer :f newname 2) save it :w 3) (optionally) !rm oldname. The advantage is that your undo history is preserved.
    – kynan
    Commented Sep 20, 2011 at 14:12
  • 4
    :saveas is better in that regard, @rampion -- and does what @kynan wrote.
    – lericson
    Commented Feb 9, 2017 at 15:56
  • 2
    What does the # represent in :e#?
    – fstamour
    Commented Mar 17, 2021 at 13:41
58

Short, secure, without plugin:

:sav new_name
:!rm <C-R>#  // or !del <C-R># for windows

control + R, # will instantly expand to an alternate-file (previously edited path in current window) before pressing Enter. That allows us to review what exactly we're going to delete. Using pipe | in such a case is not secure, because if sav fails for any reason, # will still point to another place (or to nothing). That means !rm # or delete(expand(#)) may delete completely different file! So do it by hand carefully or use good script (they are mentioned in many answers here).

Educational

...or try build a function/command/script yourself. Start from sth simple like:

command! -nargs=1 Rename saveas <args> | call delete(expand('#')) | bd #

after vimrc reload, just type :Rename new_filename. What is the problem with this command?

Security test 1: What does:Rename without argument?

Yes, it deletes file hidden in '#' !

Solution: you can use eg. conditions or try statement like that:

command! -nargs=1 Rename try | saveas <args> | call delete(expand('#')) | bd # | endtry

Security test 1: :Rename (without argument) will throw an error:

E471: Argument required

Security test 2: What if the name will be the same like previous one?

Security test 3: What if the file will be in different location than your actual?

Fix it yourself. For readability you can write it in this manner:

function! s:localscript_name(name):
  try
    execute 'saveas ' . a:name
    ...
  endtry
endfunction
command! -nargs=1 Rename call s:localscript_name(<f-args>)

notes

  • !rm # is better than !rm old_name -> you don't need remember the old name

  • !rm <C-R># is better than !rm # when do it by hand -> you will see what you actually remove (safety reason)

  • !rm is generally not very secure... mv to a trash location is better

  • call delete(expand('#')) is better than shell command (OS agnostic) but longer to type and impossible to use control + R

  • try | code1 | code2 | tryend -> when error occurs while code1, don't run code2

  • :sav (or :saveas) is equivalent to :f new_name | w - see file_f - and preserves undo history

  • expand('%:p') gives whole path of your location (%) or location of alternate file (#)

0
38

You can also do it using netrw

The explore command opens up netrw in the directory of the open file

:E

Move the cursor over the file you want to rename:

R

Type in the new name, press enter, press y.

1
  • great! i did not even know about the netrw. Commented Jun 27, 2015 at 19:31
37

If the file is already saved:

:!mv {file location} {new file location}
:e {new file location}

Example:

:!mv src/test/scala/myFile.scala src/test/scala/myNewFile.scala
:e src/test/scala/myNewFile.scala

Permission Requirements:

:!sudo mv src/test/scala/myFile.scala src/test/scala/myNewFile.scala

Save As:

:!mv {file location} {save_as file location}
:w
:e {save_as file location} 


For Windows Unverified

:!move {file location} {new file location}
:e {new file location}
2
  • 7
    You could at least explain why you down voted this answer.
    – Benjamin
    Commented Oct 22, 2015 at 5:32
  • I didn't down vote, but this is not the fastest solution, though it's my fallback solution.
    – Brenden
    Commented Nov 22, 2020 at 0:54
34

I'd recommend :Rename from tpope's eunuch for this.

It also includes a bunch of other handy commands.

The Rename command is defined as follows therein currently (check the repo for any updates!):

command! -bar -nargs=1 -bang -complete=file Rename :
  \ let s:file = expand('%:p') |
  \ setlocal modified |
  \ keepalt saveas<bang> <args> |
  \ if s:file !=# expand('%:p') |
  \   call delete(s:file) |
  \ endif |
  \ unlet s:file
19

For renaming existing file without using plugins you should use command

:Explore

This command allow you explore files in.directory, delete or rename them. than you should navigate to neccessary file in explorer than type R command which will allow you to rename file name

18
sav person.haml_spec.rb | call delete(expand('#'))
1
  • nice! didn't know about call delete(expand('#'))
    – Kyle Wild
    Commented Aug 18, 2011 at 23:40
13
:!mv % %:h/new_name

Register % contains the name of the current file.'%:h'shows the directory 'head' containing the current file, e.g.: %:hreturns /abc/def when your file full path is abc/def/my.txt

11

There’s a function in Gary Bernhardt’s .vimrc that handles this.

function! RenameFile()
let old_name = expand('%')
let new_name = input('New file name: ', expand('%'), 'file')
if new_name != '' && new_name != old_name
    exec ':saveas ' . new_name
    exec ':silent !rm ' . old_name
    redraw!
endif
endfunction
map <leader>n :call RenameFile()<cr>
2
  • 7
    Downvote me all you like. At least I can rename files. Commented Oct 23, 2015 at 17:07
  • 1
    This is a great answer, no extra plugin required.
    – wpp
    Commented Feb 19, 2016 at 12:49
8

Vim does have a rename function, but unfortunately it does not retain the history.

The easiest OS agnostic way to rename a file without losing the history would be:

:saveas new_file_name
:call delete(expand('#:p'))

expand('#:p') returns the full path of the older file.

Use :bd # if you also want to delete the older file from the buffer list.

Or create a plugin

If you want to use a quick command to rename the file, add a new file under ~/.vim/plugin with the following contents:

function! s:rename_file(new_file_path)
  execute 'saveas ' . a:new_file_path
  call delete(expand('#:p'))
  bd #
endfunction

command! -nargs=1 -complete=file Rename call <SID>rename_file(<f-args>)

The command Rename will help you to quickly rename a file.

1
  • :call delete('<C-r>#') is easier to write.
    – MaikoID
    Commented Oct 28, 2014 at 15:56
8

There's a sightly larger plugin called vim-eunuch by Tim Pope that includes a rename function as well as some other goodies (delete, find, save all, chmod, sudo edit, ...).

To rename a file in vim-eunuch:

:Move filename.ext

Compared to rename.vim:

:rename[!] filename.ext

Saves a few keystrokes :)

1
  • And it indeed has some other very useful functions ! Commented Oct 16, 2014 at 8:51
7

How about this (improved by Jake's suggestion):

:exe "!mv % newfilename" | e newfilename
4
  • Hmmm, I should clarify that it worked on MacVim yesterday but I was sshed into a server and tried it today and the 2nd command didn't seem to be treated as a colon command...
    – murftown
    Commented Dec 19, 2011 at 17:32
  • 1
    Actually now it isn't working on MacVim either. Back to the drawing board! :)
    – murftown
    Commented Dec 19, 2011 at 18:34
  • 2
    It should be :exe "!mv % newfilename" | e newfilename
    – Jake
    Commented Sep 27, 2012 at 18:23
  • Thanks Jake, that's a bit better than my solution. Updated.
    – murftown
    Commented Aug 1, 2013 at 15:13
3

I don't know if this is the "easiest" method, but assuming you've already saved your file (:w) I would invoke the shell (:sh) and do a simple cp foo foo.bak To go back to editor use Ctrl-D/Exit. Useful list of vi editor commands on this link

3
  • This will copy the file, not rename it.
    – innaM
    Commented Jul 30, 2009 at 9:04
  • Ah - I misread "I would like to continue editing person.haml_spec.rb" My bad!
    – DBMarcos99
    Commented Jul 30, 2009 at 9:07
  • I suppose you could :! cp foo foo.new and then :e foo.new ?
    – DBMarcos99
    Commented Jul 30, 2009 at 9:11
3

You can also use :f followed by :w

1
  • 3
    This does not remove the old file. Commented Nov 19, 2013 at 19:36
3

:h rename() is by far the easiest and cleanest method. Just call it :call rename("oldname", "newnane")

1

This little script isn't perfect (the extra carriage-return you have to press) but it get's the job done.

function Rename()
  let new_file_name = input('New filename: ')
  let full_path_current_file = expand("%:p")
  let new_full_path = expand("%:p:h")."/".new_file_name
  bd    
  execute "!mv ".full_path_current_file." ".new_full_path
  execute "e ".new_full_path
endfunction                                                                                                                                                                                                                                 

command! Rename :call Rename()
nmap RN :Rename<CR>
0

Another way is to just use netrw, which is a native part of vim.

:e path/to/whatever/folder/

Then there are options to delete, rename, etc.

Here's a keymap to open netrw to the folder of the file you are editing:

map <leader>e :e <C-R>=expand("%:p:h") . '/'<CR><CR>
0

:sav newfile | !rm #

Note that it does not remove the old file from the buffer list. If that's important to you, you can use the following instead:

:sav newfile | bd# | !rm #

0

It's also possible to open a terminal from within vim with :terminal, then you can rename it from a terminal in an open buffer without technically leaving vim. It's not the same as issuing one succinct command but it is also a possibility.

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