20

Is there any way of executing a mv command without typing the full path in the second argument?

Example:

mv my/file/that/has/a/really/long/path/foo.bar some_magic_operator_that_means_the_same_directory/foo.baz

4
  • 1
    Any reason you can't just cd to the directory and mv from there? – zpletan Mar 27 '12 at 18:35
  • I frequently find myself executing these kinds of commands across multiple directories in my day to day work. I often need to execute several commands from a given parent directory. – Finbarr Mar 27 '12 at 19:10
  • Somehow I found that using !! (double exclamation signs) in a terminal uses to run the last command executed. You can also add parameters/text to the last command but never tried to change/remove text from the last command. Try it and if you succeed I will drop this like an answer. Good luck! – Geppettvs D'Constanzo Mar 27 '12 at 20:05
  • Remember that after cd to whatever path you can then cd - to go back instantly. – bloody Apr 10 '20 at 20:47
36

You can use bash's brace expansion. This:

mv my/file/that/has/a/really/long/path/foo.{bar,baz}

will expand into:

mv my/file/that/has/a/really/long/path/foo.bar my/file/that/has/a/really/long/path/foo.baz

and then mv is run with those two arguments. See http://wiki.bash-hackers.org/syntax/expansion/brace for more on brace expansion.

1
  • 3
    That's glorious. I didn't know you could do that. – Finbarr Mar 27 '12 at 20:08
5

As an alternative to brace expansion, you could use the bash shell's history expansion features:

  • ! introduces a history expansion
  • # event designator denoting the current command
  • $ word designator referring to the last argument

You can perform substitutions on the expansion using a sed-like s/pattern/replacement syntax e.g.

somecommand path/to/foo.bar !#$:s/.bar/.baz

Ex.

$ mv -v somepath/Original/Dir3/SubDir1/foo.bar !#$:s/.bar/.baz
mv -v somepath/Original/Dir3/SubDir1/foo.bar somepath/Original/Dir3/SubDir1/foo.baz
'somepath/Original/Dir3/SubDir1/foo.bar' -> 'somepath/Original/Dir3/SubDir1/foo.baz'

If you want the path specifically (for example, to mv a file to a completely different name that is not easily obtained by substitution), you can use the h modifier:

$ mv -v somepath/Original/Dir3/SubDir1/foo.baz !#$:h/baz.foo
mv -v somepath/Original/Dir3/SubDir1/foo.baz somepath/Original/Dir3/SubDir1/baz.foo
'somepath/Original/Dir3/SubDir1/foo.baz' -> 'somepath/Original/Dir3/SubDir1/baz.foo'

For other options, including readline key combinations to yank the last argument, see How to repeat currently typed in parameter on bash console?

2

You might try:

pushd .
cd /really/long/directory/name/
mv whatever.1 whatever.2
popd
1
  • Use instead: cd /really/long/dir/name/; mv what.1 what.2; cd - – bloody Apr 10 '20 at 20:46
2

With a variable

  1. Save the directory in a variable : `DIR=./really/long/path/
  2. use move : mv "$DIR"foo.bar "$DIR"foo.bz

In one line : DIR=./really/long/path/; mv "$DIR"foo.bar "$DIR"foo.bz


Changing directory

  1. You could also cd to the directory you want to work in : cd ./really/long/path
  2. then change the file name : mv foo.bar foo.bz

In one line : cd ./really/long/path && mv foo.bar foo.bz

2
  • 1
    that second one looks familiar ;-) – zpletan Mar 27 '12 at 18:44
  • 2
    Best use && in that last one-liner. Otherwise, if the cd fails, the mv will be run in the wrong directory, potentially overwriting a file. With cd ./really/long/path && mv foo.bar foo.baz, mv will only be run if cd succeeds in changing directory. – geirha Mar 27 '12 at 19:02
-3

You can you alias command to short the directory name:

alias src='/directory/name/of/source'
alias dst='/directory/name/of/destination'
mv src dst
1
  • 1
    -1 alias test='/var/log' ; cd test gives -bash: cd: test: No such file or directory. – zpletan Mar 27 '12 at 18:50

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