Coder Perfect

Is it possible to have mv generate the directory to be transferred to if it doesn’t already exist?

Problem

So, if I’m in my home directory and want to move foo.c to /bar/baz/foo.c, but those folders don’t exist, is there a method to have those directories created automatically, so that all you have to do is type foo.c?

mv foo.c ~/bar/baz/ 

and everything would fall into place? I suppose you could alias mv to a basic bash script that checks if those directories exist and then calls mkdir and then mv if they don’t, but I wanted to see if anyone had a better suggestion.

Asked by Paul Wicks

Solution #1

How about this one-liner (in bash):

mkdir --parents ./some/path/; mv yourfile.txt $_

Breaking that down:

mkdir --parents ./some/path
# if it doesn't work; try
mkdir -p ./some/path

After that, it creates the directory (containing all intermediary directories), and then:

mv yourfile.txt $_

moves the file to that directory ($ expands to the preceding shell command’s last parameter, i.e. the newly created directory).

I’m not sure how well this will work in different shells, but it may help you figure out what to search for.

Here’s an example of how to use this technique:

$ > ls
$ > touch yourfile.txt
$ > ls
yourfile.txt
$ > mkdir --parents ./some/path/; mv yourfile.txt $_
$ > ls -F
some/
$ > ls some/path/
yourfile.txt

Answered by KarstenF

Solution #2

mkdir -p `dirname /destination/moved_file_name.txt`  
mv /full/path/the/file.txt  /destination/moved_file_name.txt

Answered by Billmc

Solution #3

Save as a script named mv.sh

#!/bin/bash
# mv.sh
dir="$2" # Include a / at the end to indicate directory (not filename)
tmp="$2"; tmp="${tmp: -1}"
[ "$tmp" != "/" ] && dir="$(dirname "$2")"
[ -a "$dir" ] ||
mkdir -p "$dir" &&
mv "$@"

Alternatively, add it to the end of your /.bashrc file as a function that replaces mv on every new terminal. Instead of having to read a script file every time, bash may preserve its memory by using a function.

function mvp ()
{
    dir="$2" # Include a / at the end to indicate directory (not filename)
    tmp="$2"; tmp="${tmp: -1}"
    [ "$tmp" != "/" ] && dir="$(dirname "$2")"
    [ -a "$dir" ] ||
    mkdir -p "$dir" &&
    mv "$@"
}

Example usage:

mv.sh file ~/Download/some/new/path/ # <-End with slash

These are based on Chris Lutz’s contribution.

Answered by Sepero

Solution #4

You can use the command mkdir:

mkdir -p ~/bar/baz/ && \
mv foo.c ~/bar/baz/

A simple script to automate the process (untested):

#!/bin/sh

# Grab the last argument (argument number $#)    
eval LAST_ARG=\$$#

# Strip the filename (if it exists) from the destination, getting the directory
DIR_NAME=`echo $2 | sed -e 's_/[^/]*$__'`

# Move to the directory, making the directory if necessary
mkdir -p "$DIR_NAME" || exit
mv "$@"

Answered by strager

Solution #5

No, it appears that the answer is no:). I don’t want to make an alias or func just to do this, especially if it’s a one-time occurrence and I’m already typing the mv command, but I did find something that works:

mv *.sh  shell_files/also_with_subdir/ || mkdir -p $_

If mv fails (dir does not exist), it will create it (the final parameter to the preceding command, so $ already contains it). So simply execute this command, then up to re-run it, and mv should work this time.

Answered by Pat

Post is based on https://stackoverflow.com/questions/547719/is-there-a-way-to-make-mv-create-the-directory-to-be-moved-to-if-it-doesnt-exis