I have two directories which I need to rsync the contents of only subdirectories that are already present in the destination directory. For example:

Source directory:

  • folder A
  • folder B
  • folder C
  • folder D
  • folder E

Destination directory:

  • folder B
  • folder D
  • folder Z

I need to rsync the only contents of folders B and folder D from Source to Destination (and folder Z doesn't exist at source, so should be ignored). Equally, I do not need Destination directory to have folders A, C and E copied to it.

Essentially a "For all subdirectories in Destination, If the same subdirectory exists in source, rsync the contents of that subdirectory from source".

If it helps, these are all local directories.

Hopefully that makes sense. Thank you for the help!

  • 1
    If /D/ exists in the destination but not /D/S, should /D/S/F be copied? Commented Apr 15, 2020 at 18:20

3 Answers 3


You could use a script like this.

    cd destination &&
        for d in *
            [ -d "$d" -a -d source/"$d" ] && rsync -a source/"$d" .

If it's standalone you don't need the ( ... ) brackets as they only exist to localise the change of directory.

Add --delete to the rsync if you want files in the destination to be removed when they are no longer present in the source.


Create the following bash script, change the paths to the source and destination directory and execute it.



shopt -s nullglob
  for dir in "$destination/"*/; do
    dirname=$(basename "$dir")
    if [ -d "$source/$dirname" ]; then
      printf '+ /%s/***\n' "$dirname"
  printf -- '- *\n'
} > "$source/filter.rules"

#rsync -av --filter="merge $source/filter.rules" "$source"/ "$destination"

This would create a file filter.rules in the source directory with the following content:

+ /folder B/***
+ /folder D/***
- *

The first line + /folder B/*** is the short syntax for

  • + /folder B/ include the directory
  • + /folder B/** include files and subdirectories

and - * excludes files and directories in the root.

If the rules look as expected, uncomment the last line and run the script again to rsync the directories using a merge filter.


The --existing flag is what you're looking for. From the man page:

--existing, --ignore-non-existing

This  tells  rsync  to  skip  creating  files (including 
directories) that do not exist yet on the destination.  If this option is combined 
with the --ignore-existing option, no files will be updated (which can be useful 
if all you want to do is delete extraneous files).

This option is a transfer rule, not an exclude, so it doesn’t affect the data that 
goes into the file-lists, and thus it doesn’t affect deletions.  It just limits 
the files that the  receiver requests to be transferred.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .