[vim] Renaming the current file in Vim

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?

This question is related to vim vi

The answer is


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


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


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>

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

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>

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.


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

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.


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>

: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 #


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

:exe "!mv % newfilename" | e newfilename

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


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 :)


sav person.haml_spec.rb | call delete(expand('#'))

You can also use :f followed by :w


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}

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.


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


:!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


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