36

Often I will work out of the root of a rails directory where I find my self navigating the same path twice every time I would like to move a file:

mv app/views/layouts/application.html.erb app/views/layouts/application.html.haml

The haml is just one of may examples where I need to change the file name without modifying the directory it currently lives in and without changing directory. Is there a way to achieve this?

rudolph9
  • 1,425
  • 1
  • 17
  • 24
  • I remember seeing a question with an accepted answer nearly identical to mine. However I cannot find it so I've answered your question for now, at least until someone stumbles across the link. – jw013 Apr 05 '12 at 07:41
  • 1
    http://unix.stackexchange.com/questions/6035/when-do-you-use-brace-expansion – bbaja42 Apr 05 '12 at 07:45
  • 3
    While the answers are the same, the questions are rather different. That one is "I have a tool, but what's it good for?" and this one is "I have a problem, what tool should I use?" It's probably worth keeping both. – cjm Apr 05 '12 at 08:14

4 Answers4

59

Use brace expansion:

mv very/long/path/to/filename.{old,new}

would expand to

mv very/long/path/to/filename.old very/long/path/to/filename.new
jw013
  • 50,274
  • 9
  • 137
  • 141
8

If you're going to work in a directory, you can switch to it temporarily.

pushd app/views/layouts
mv application.html.erb application.html.haml
popd

Under Linux, you can use the rename utility (called rename.ul under Debian, Ubuntu and derivatives) to change a part of the file name (which can be in the directory part). rename foo bar path/to/file changes the first occurrence of foo in path/to/file to bar. If a file name doesn't contain the first string, the file is left in place.

rename .erb .haml app/views/layouts/application.html.erb
rename .erb .haml app/views/layouts/*.html.erb       # do several in one go
rename .erb .haml app/views/layouts/application.*    # never mind if application.js and application.html.gz also exist

When you have several consecutive words in a comman line that share a common stem, you can use brace expansion:

mv app/views/layouts/application.html.{erb,haml}
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
4

You could cd in the directory in a sub-shell:

(cd app/views/layouts && mv application.html.erb application.html.haml)

Here, the parentheses execute the commands in a new bash shell process.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
jfg956
  • 5,988
  • 3
  • 22
  • 24
3

You can define function:

mv-rename () {
  mv -- "${1}" "$(dirname -- "${1}")/${2}"
}

Usage:

mv-rename app/views/layouts/application.html.erb application.html.haml
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
anlar
  • 4,096
  • 3
  • 30
  • 54