I use :saveas to move a file while maintaining its undo history. Most of the time I immediately delete the old file. So if I'm editing foo.txt I'll issue

:saveas bar.txt
:!rm foo.txt

I wanted to make this into a single command, so I'm trying

command! -nargs=* Move :call delete(expand('%')) | saveas arg1

But if I issue

:Move bar.txt

instead it creates a new file called (literally) arg1

I'm guessing I misunderstand how arg1 works (and probably how | works).

Is there a better way to do this anyway?


Use <args> when referencing command arguments. <args> will expand to the arguments passed to the command. Also, while not strictly required, because you always want to pass one argument to your command (the new filename) you should probably use -nargs=1.

I would also recommend saving the new file and then deleting the old file, just to be safe. You can do this by using # (the alternate file name) instead of % (the current file name) inside expand(). After using :saveas, the alternate file name is set to the the old file name.

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

Optionally, you could expand this to use a ! in a way that is analogous to :w! (forcefully write) with the -bang option:

command! -nargs=1 -bang Move :saveas<bang> <args> | call delete(expand('#'))

In this case, <bang> will be expanded to ! if the command was executed with !, otherwise it will expand to nothing.

Relevant help:

:h :saveas
:h :_#
:h :command-nargs
:h <args>
:h :command-bang
:h <bang>

If plugins are an option, tpope's eunuch plugin offers :Move to anywhere and :Rename within the current directory commands, among many others.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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