Rsync will create ONE directory level when it is the last component in the target path. Any other directory levels must already exist. If you need to have more than that number of levels created, AND if the directory levels to be created all exist in the source tree, you can get rsync to do this. The method involves using the --include and --exclude options to select the specific directory to be copied, and specify the source and target at a higher level (so that the the parent of the target exists). Unfortunately, it is complicated, and gets more complicated with more levels. But basically, you shorten the source and target paths equally, and fill in the paths through the --include options. You also use the --exclude options to block copying of other directory levels.
Here is a command example:
Code:
rsync -av --include projects --include projects/newprogram --include 'projects/newprogram/**' --exclude 'projects/**' --exclude '**' /home/skaperen/programs/. skaperen@backupserver:/home/skaperen/programs
This copies "/home/skaperen/programs/projects/newprogram" and all its subdirectories.
The order of the --include and --exclude options is important to rsync. It checks each file to be considered against these options in order and applies the first match. This will create "/home/skaperen/programs" in the target if it does not exist. Ending the source path with "/." ensures that if the target directory already exists, another directory called "programs" will not be created in it (which would end up with "/home/skaperen/programs/programs" with a duplicate of everything). The subdirectories "projects" and "projects/newprogram" will be created as recursive subdirectories.
So, for your situation, find the directory level where you can be sure the parent directory really does exist (perhaps the home directory as in my example). Then express every level you want to copy as discrete --include options. Use the "**" (a double asterisk matches multiple directory levels while a single asterisk matches exactly one directory level). Then add --exclude options to exclude everything else at each level. Be sure to do an --exclude for "**" as the final one.
Don't forget to append "/." on the source path to avoid placing the source directory inside the target directory (or leave it off if that is your intention). You can append "/." on the target path if you want to prevent it from creating it when it does not exist. You need to put the options with * or ** in quotes to prevent your shell from expanding it from existing files.
I hope that helps. If you need to change a directory name so the target is different than the source, you need to do that as the target and source arguments (not in --include). That means the parent directory of a name-changed target must exist. If the above cannot be achieved because of the renaming needs, then you will have to resort to using ssh into the target to run "mkdir -p" with the target path to get the needed directories to exist.