463

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?

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
Sam Saffron
  • 128,308
  • 78
  • 326
  • 506

22 Answers22

520

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.

soulmerge
  • 73,842
  • 19
  • 118
  • 155
  • 1
    Thx, Explore gets the job done, it is however a little awkward – Sam Saffron Jul 30 '09 at 09:19
  • 3
    :Explore works great! I'm getting rid of NERD-tree in favor of this! – bzx Jul 18 '11 at 09:17
  • 6
    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. – Rafael Bugajewski Sep 07 '11 at 17:43
  • @bzx: same here, I'm gonna map existing shortcut to open NerdTree to Explore :) – Dzung Nguyen Oct 11 '11 at 03:32
  • 172
    You might also like :Sex (shorthand for __split explore__ :-) ) – Peter Jankuliak Dec 07 '11 at 03:03
  • 8
    Also, :e will open explore in the current pane. Less exciting than :Sex but more efficient ;). – Josh Jul 31 '12 at 02:35
  • 76
    For the intrepid, vertical :Sex is :Vex. – hobbes3 May 20 '13 at 16:45
  • 2
    @bzx NERDTree does this, except you need to 'move': open NERDTree, `mm` then enter new name. – TankorSmash Dec 01 '13 at 20:34
  • 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 Apr 11 '14 at 16:48
  • 4
    Whoops, I meant to put :e. (with the period at the end). – Josh Apr 11 '14 at 20:14
  • 1
    This is actually *the* solution in a scenario like this one: I want to create a new file `file`. I misspell the name on command line (`vim fule`), and I notice my mistake just before saving. Then, `:saveas file` is the easiest solution. This actually happened to me about five minutes ago. – Palec Sep 14 '15 at 17:18
  • 1
    Renaming in the explorer DOESN'T open the new named file in my open buffers! They still reference the old filename, which is not only awkward (You have to close the buffer and open a new one on the new filename) but also dangerous (you could not notice, and continue saving changes to the old filename instead of the new.) – Jonathan Hartley May 19 '16 at 21:49
  • 2
    `:Sex` or `:Vex`, you'll need `CTRL + W` and then `Up/Down/Left/Right arrow key` to navigate between the `split windows` – Aakash Mar 02 '17 at 04:06
  • One downside of `:saveas` is that it will lose the execute permission if you were editing a script. `netrw` Rename will keep the permissions. – wisbucky Sep 12 '19 at 23:00
208

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

:Gmove newname

This will:

  1. Rename your file on disk.
  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
ISQ
  • 2,704
  • 1
  • 14
  • 8
  • 4
    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? – Frido Emans Sep 16 '15 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 Dec 13 '16 at 15:53
  • 10
    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 %` which appends the current path/filename. – shmup May 08 '18 at 21:32
  • Doesn't work with new files that are not added to git yet. – blues Jul 30 '19 at 09: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 Jul 31 '19 at 18:12
110

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...

yozzz
  • 1,267
  • 1
  • 22
  • 30
woto
  • 2,893
  • 1
  • 29
  • 24
91

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

Ry-
  • 218,210
  • 55
  • 464
  • 476
innaM
  • 47,505
  • 4
  • 67
  • 87
  • `code`:Rename %:p:h/_new_file_name.html.erb will save it in the same directory as the file being renamed. – mkly May 05 '11 at 19:34
  • 3
    :Rename 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. – Thomas Hunter II May 14 '11 at 20:11
  • 10
    [This updated version of Rename.vim](http://www.vim.org/scripts/script.php?script_id=2724) handles CWD correctly - always saves file in the directory of original one. – ku1ik Sep 04 '11 at 17:56
  • 2
    @sickill Here's an even better version IMO that tries to be smart, if the new file name contains a "/" it uses the full path, otherwise it assumes the current directory https://github.com/DelvarWorld/configs/blob/master/bundle/Rename/plugin/Rename.vim – Andy Ray Dec 05 '11 at 20:13
  • @AndyRay The link is dead. Here is an updated link: https://github.com/DelvarWorld/configs/blob/master/.vim/bundle/Rename/plugin/Rename.vim –  Mar 22 '13 at 13:06
  • 1
    All of these versions fail if there are spaces in the directory that the file resides in and the directory is not explicitly specified. –  Mar 22 '13 at 13:42
  • 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: https://github.com/aehlke/vim-rename3 Feel free to submit pull requests for even smarter functionality! – aehlke Jul 31 '13 at 21:40
  • 1
    Sourceforge is under maintenance so the link is gone. Please add at least the plugin name to the answer, so we can google around this. – kikito Jul 17 '15 at 09:52
  • 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. – JackHasaKeyboard Aug 23 '17 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 Aug 24 '17 at 15:06
  • @JackHasaKeyboard, but who even uses that absurdly named directory? I use `apps` myself. Sure it's a pain to have to customize every install, but I feel it's worth it in the long run. – SO_fix_the_vote_sorting_bug Aug 09 '20 at 19:43
84
  • 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.
gimel
  • 83,368
  • 10
  • 76
  • 104
56

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 (#)

Mesco
  • 1,254
  • 13
  • 21
39

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.

Ben
  • 2,661
  • 28
  • 31
38

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}
Benjamin
  • 1,832
  • 1
  • 17
  • 27
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
blueyed
  • 27,102
  • 4
  • 75
  • 71
Gavin Gilmour
  • 6,833
  • 4
  • 40
  • 44
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('#'))
Maxim Kim
  • 6,192
  • 2
  • 29
  • 28
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

Yossarian42
  • 1,950
  • 17
  • 14
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>
Jezen Thomas
  • 13,619
  • 6
  • 53
  • 91
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.

Alex
  • 1,618
  • 1
  • 17
  • 25
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 :)

shender
  • 1,243
  • 13
  • 17
7

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

:exe "!mv % newfilename" | e newfilename
murftown
  • 1,287
  • 1
  • 10
  • 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

DBMarcos99
  • 465
  • 3
  • 12
3

You can also use :f followed by :w

3

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

Lampros
  • 321
  • 3
  • 10
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>
Jonas Geiregat
  • 5,214
  • 4
  • 41
  • 60
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>
dechimp
  • 99
  • 1
  • 3
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 #

sitaktif
  • 1,594
  • 13
  • 15