Renaming the current file in Vim
VimViVim Problem Overview
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?
Vim Solutions
Solution 1 - Vim
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.
Solution 2 - Vim
If you use git and already have the tpope's plugin fugitive.vim then simply:
:Gmove newname
This will:
- Rename your file on disk.
- Rename the file in git repo.
- Reload the file into the current buffer.
- Preserve undo history.
If your file was not yet added to a git repo then first add it:
:Gwrite
Solution 3 - Vim
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...
Solution 4 - Vim
There's a little plugin that lets you do this.
Solution 5 - Vim
- 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
.
Solution 6 - Vim
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).
...or try build a function/command/script yourself. Start from sth simple like: Educational
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 (#
)
Solution 7 - Vim
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}
Solution 8 - Vim
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.
Solution 9 - Vim
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
Solution 10 - Vim
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
Solution 11 - Vim
sav person.haml_spec.rb | call delete(expand('#'))
Solution 12 - Vim
:!mv % %:h/new_name
Register %
contains the name of the current file.'%:h'
shows the directory 'head' containing the current file, e.g.: %:h
returns /abc/def
when your file full path is abc/def/my.txt
Solution 13 - Vim
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>
Solution 14 - Vim
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.
Solution 15 - Vim
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 :)
Solution 16 - Vim
How about this (improved by Jake's suggestion):
:exe "!mv % newfilename" | e newfilename
Solution 17 - Vim
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
Solution 18 - Vim
You can also use :f followed by :w
Solution 19 - Vim
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>
Solution 20 - Vim
:h rename()
is by far the easiest and cleanest method.
Just call it
:call rename("oldname", "newnane")
Solution 21 - Vim
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>
Solution 22 - Vim
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: