12

If I am in ~/blob and I have a file in ~/blob/a_long_directory_name/c/x.x

I can type

mv blob/a_long_directory_name/c/x.x blob/a_long_directory_name/even_more/y.y

Is there any shortcut whereby I can type something shorter that uses the directory path in the first param (not my current directory though), e.g.

mv blob/a_long_directory_name/c/x.x $same_dir/y.y

where something like $same_dir would point to the dir of param 1

0

3 Answers 3

27

With bash, you could use brace expansion

mv blob/a_long_directory_name/{c/x.x,evenmore/y.y}
0
8

To minimize the amount of typing, it's probably easiest to do it in two steps. CD to the directory, then move.

If you only have one command, you can use a subshell:

$ (cd blob/a_long_directory_name/c/ && mv x.x y.y )

That means the cd will only take effect in the subshell, the mv will only happen if the cd succeeds, and the working directory of your current shell won't change.

If you have more than one command, use the directory stack.

$ pushd blob/a_long_directory_name/c/
$ mv x.x y.y
$ mv z.z q.q
$ popd
5
  • This doesn't address the even_more relative path ...
    – Useless
    Sep 5, 2013 at 17:23
  • That is correct. The $same_dir example seemed to ignore it as well. Sep 5, 2013 at 17:58
  • +1 I like it. Very easy to remember and do and that is key to me Sep 5, 2013 at 18:42
  • Interesting, since it doesn't do what you asked for. Maybe your question isn't exactly what you intended?
    – Useless
    Sep 6, 2013 at 14:17
  • Useless, I updated my title to clarify that it's about cp/mv files and keep them in that same directory, even though I am in another. btw your username is cute but it makes comments look silly when used in them :) Sep 7, 2013 at 0:10
5

You could use your shell's text substitution capabilities. In bash, you could use a beast like:

mv blob/a_long_directory_name/c/xx !#:$:gs^c/xx^evenmore/yy

To break it down:

!# is the current line typed so far

:$ asks to pick the last word (replace with a number n to pick n'th word) of the string under consideration (!# in this case). The last word of the line typed so far would be the previous word.

:gs^xx^yy does global (g) textual substitution (s) on the resulting word, replacing 'xx' with 'yy'. ^ is just a delimiter for the s command to allow using / in your patterns.

This method is slightly more general as it lets you replace any part of the path ('xx') with any other word ('yy').

Finally, like with any history manipulation, it's good to have appropriate shell options set (e.g. in ~/.bashrc). In this case

shopt -s histverify

will display the edited line after you press return, so you can still edit it and check for errors.

Why you'd use a construct like that I'm not sure, but it works in this case.

3
  • a) Too much line noise (compare to an elegant brace expansion) b) Does not solve the OP's problem: they want to replace c/x.x with evenmore/y.y keeping the original path prefix.
    – Joseph R.
    Sep 5, 2013 at 18:11
  • Your second comment was a simple omission on my part, that required a simple edit to fix. I don't see how this answer deserved a downvote. With the edit (technicality), it does solve the problem and is more general as it allows swapping any part of the path (I often used something similar on $PWD). Sure, maybe it's not the most elegant but it points to the fact that shell does have textual substitutions and word designators, which some users might still find useful to research.
    – Wojtek
    Sep 5, 2013 at 18:20
  • OK. I stand corrected.
    – Joseph R.
    Sep 5, 2013 at 19:25

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.