11

I often find myself using mv to rename a file. E.g.

mv app/models/keywords_builder.rb app/models/keywords_generator.rb

Doing so I need to write (ok, tab complete) the path for the second parameter. In this example it isn't too bad but sometimes the path is deeply nested and it seems like quite a bit of extra typing.

Is there a more efficient way to do this?

Mikel
  • 24,855
  • 8
  • 65
  • 66
Jack Kinsella
  • 4,491
  • 3
  • 38
  • 56

5 Answers5

22

And another way: brace expansion.

mv app/models/keywords_{builder,generator}.rb

In general,

before{FIRST,SECOND}after

expands to

beforeFIRSTafter beforeSECONDafter

So it's also useful for other renames, e.g.

mv somefile{,.bak}

expands to

mv somefile somefile.bak

It works in bash and zsh.

More examples:

Mikel
  • 24,855
  • 8
  • 65
  • 66
10

You can use history expansion like this:

mv app/modules/keywords_builder.rb !#^:h/keywords_generator.rb
  1. ! introduces history expansion.
  2. # refers to the command currently being typed
  3. ^ means the first argument
  4. :h is a modifier to get the "head", i.e. the directory without the file part

It's supported in bash and zsh.

Docs:

Mikel
  • 24,855
  • 8
  • 65
  • 66
4

One way is to type the first file name and a space, then press Ctrl+w to delete it. Then press Ctrl+y twice to get two copies of the file name. Then edit the second copy.

For example,

mv app/models/keywords_builder.rb <Ctrl+W><Ctrl+Y><Ctrl+Y><edit as needed>
Mikel
  • 24,855
  • 8
  • 65
  • 66
geekosaur
  • 59,309
  • 11
  • 123
  • 114
  • I *really* like the idea. I just can't find an easy way to "move backwards" to the space with the default bash bindings. `Alt+B` four times? – Mikel Mar 31 '11 at 20:47
  • `Ctrl`+`a`, `Alt`+`f`? Or `Ctrl`+`r`, `Space`. Or in `set -o vi`: `Esc`, `T`, `Space`. – geekosaur Mar 31 '11 at 20:49
  • Oo! `Ctrl+W` would be great here. – Mikel Mar 31 '11 at 20:49
  • ... then `Alt+Backspace`, `Alt+Backspace`, `Alt+Backspace` to delete the file name part in the destination. – Mikel Mar 31 '11 at 20:53
  • @geekosaur: Did you want to write that way up? It's heavily based on yours, so feel free to do so. – Mikel Mar 31 '11 at 20:58
  • that are the usual emacs commands, alt-backspace to delete word, ctrl-a begin end of line, ctrl-e end of line .... – flolo Mar 31 '11 at 22:51
  • Exactly. (Well, aside from `Ctrl`+`w` which is standard tty behavior instead of Emacs' `kill-region`). – geekosaur Mar 31 '11 at 22:55
  • @flolo: The reason why `Ctrl+W` is better in this case is that it deletes until the previous whitespace, but `Alt+Backspace` deletes until the previous non-letter (e.g. `/` or `.`), so it requires more keypresses in this case. I was trying to find the fewest keystrokes. – Mikel Apr 01 '11 at 02:00
1

or cd apps/models && mv keywords_builder.rb keywords_generator.rb && cd -

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
0

Combined answers of Mikel and geekosaur with additonal use of ":p"

use brace expansion to avoid first argument repetition:

mv -iv {,old_}readme.txt # 'readme.txt' -> 'old_readme.txt'

mv -iv file{,.backup} # 'file' -> 'file.backup'

use history expansion to avoid first argument repetition:

mv -iv "system file" !#$.backup # 'system file' -> 'system file.backup'

the filename can be printed using the "p" designator for further edition:

mv -iv "file with a long name" !#$:p

then press "↑" to edit the command

Łukasz Rajchel
  • 261
  • 2
  • 4