12

Occasionally, I have edited some file and want to move it to a different folder. (Typically: to a Dropbox folder, where I did not want to work to avoid giving the other owners of the folder constant updates.) I do this, for example, with

mv file.pdf ../../../Dropbox/sharedfolder/subdirectory/file.pdf

Afterwards, I often find myself wanting to change directory to the target directory of my previous move operation. I find myself hitting the up arrow, deleting the final file.pdf, holding left, deleting mv file.pdf and replacing it with cd.

Is there a faster, smarter way to do this? Is there a "move file and then change directory to" command, or a shortcut for the last used directory, or something like that?

  • 1
    if you hold CTRL+Left, it will go left by word which is faster – cat Mar 2 '17 at 20:31
  • Side comment, not an answer to your shell question: I typically just pause Dropbox whilst editing. It also ensures no other files get changed "under my feet". – Constantino Tsarouhas Mar 3 '17 at 7:26
17

If you're using bash, then its history interaction has just the shortcut for this. The word designator for the last argument of the previous command:

!!:$
designates the last argument of the preceding command. This may be shortened to !$.

Combined with a modifier to remove the last pathname component:

After the optional word designator, you can add a sequence of one or more of the valid modifiers, each preceded by a ‘:’.

h
Remove a trailing pathname component, leaving only the head.

So:

$ echo /ab/c/d
/ab/c/d
$ echo !$:h
echo /ab/c
/ab/c

The same shortcut can also be used with zsh.

  • 1
    This is so cool. – Elder Geek Mar 2 '17 at 16:32
4

If you're not changing the filename, you can omit it and mv will add it automatically; this is especially useful when moving multiple files:

mv file.pdf ../../../Dropbox/sharedfolder/subdirectory/

mv *.pdf ../../../Dropbox/sharedfolder/subdirectory/

With the directory as the last argument, you can use !!:$ or !$ as muru's answer describes.
If you're using bash with the usual defaults, you can use Alt+. instead.
(This is the readline insert-last-argument command; bind -p will list all your current bindings.)

  • 1
    note that omitting the destination filename can silently overwrite the destination file if it already existis – cat Mar 2 '17 at 20:31
  • mv always overwrites destination files silently unless you specify the options -i/--interactive or -n/--no-clobber. That's why I have alias mv='mv -i' cp='cp -i' in my .bashrc. – David Foerster Mar 14 '17 at 12:02
-1

Another approach is to create your own command dedicated for this purpose. This can be done via function which could looks like:

$ function mv-special { mv $1 $2; cd $(dirname $(echo $2-)); }

Where: (1) mv-special is the function name; (2) the variables $1 and $2 are arguments in the function who will be used by the commands mv and cd; (3) $(echo $2-) adds a wildcat character to the end of the string in var $2, and fixes the behaviour of dirname if the variable $2 contains only path; (4) $(dirname $(echo $2-)) will filter only the path from $2.

According to this answer the function could looks like:

$ function mv-special { mv $1 $2; cd ${2%/*}; }

Where: ${2%/*} will filter only the path from $2.

To be available as a command this function must be exported:

$ export -f mv-special

Usage:

$ mv-special file.pdf ../../../Dropbox/sharedfolder/subdirectory/file.pdf

or:

$ mv-special file.pdf ../../../Dropbox/sharedfolder/subdirectory/

Please pay attention to that - for both variants - the second argument ($2) must finishes with filename or slash (/).

To be our new command permanently available, the definition of the function and the export command must be appended to ~/.bashrc:

# My custom 'mv-special' command:
function mv-special { mv $1 $2; cd $(dirname $(echo $2-)); }
export -f mv-special

or:

# My custom 'mv-special' command:
function mv-special { mv $1 $2; cd ${2%/*}; }
export -f mv-special

enter image description here


Custom command can be made and via executable script file which is placed in ~/bin or in /usr/sbin: How can I create a custom terminal command (to run a script)? But to be honest, I was faced a trouble with the behaviour of cd in this scenario.

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.