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?

3 Answers3

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.

Elder Geek
  • 36,023
  • 25
  • 98
  • 183
muru
  • 197,895
  • 55
  • 485
  • 740
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.)

deltab
  • 578
  • 1
    note that omitting the destination filename can silently overwrite the destination file if it already existis – cat Mar 02 '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.

pa4080
  • 29,831