Index: trunk/backups/backup.py
===================================================================
--- trunk/backups/backup.py	(revision 40973)
+++ trunk/backups/backup.py	(revision 41067)
@@ -33,4 +33,5 @@
     [ ConfigSchemaLine('sources', True, list, SpecialSchemaProcessing.commma_separated)
     , ConfigSchemaLine('additional_args', False, list, SpecialSchemaProcessing.space_separated)
+    , ConfigSchemaLine('sub-dirs', False, list, SpecialSchemaProcessing.commma_separated)
     ]
 )
@@ -83,8 +84,4 @@
 
         self.read_config_and_schema(config, schema)
-        # self.read_copy_config_section(config, schema)
-        # self.read_tar_config_section(config, schema)
-        # self.read_rsync_config_section(config, schema)
-        # self.read_mysqldump_config_section(config, schema)
 
     def read_config_and_schema(self, config: ConfigParser, schema: ConfigSchema):
@@ -206,20 +203,38 @@
         self.target_backup_paths_ok(raise_error=True)
         backup_paths = self.default_dict['backup_paths']
-        for bp in backup_paths:
-            # if not path.exists(bp):
-            #     raise errs.ValidationError(f"ValidationError: target path does not exist: {bp}")
-
-            for s in self.rsync_dict['sources']:
-                if not path.exists(s):
-                    raise errs.ValidationError(f"ValidationError: target path does not exist: {s}")
+
+        sources = self.rsync_dict['sources']
+        for i in range(0, len(sources)):
+            source = sources[i]
+            if not path.exists(source):
+                    raise errs.ValidationError(f"ValidationError: target path does not exist: {source}")
+
+            for bp in backup_paths:
                 try:
-                    args = [s, bp]
+                    additional_args = []
                     if 'additional_args' in self.rsync_dict.keys():
-                        args = args + self.rsync_dict['additional_args']
+                        additional_args = self.rsync_dict['additional_args']
+
+                    source_and_target_args = [source, bp]
+
+                    # sub-dirs option allows items to be backed up to subdirs within
+                    # the source for better naming
+                    if 'sub-dirs' in self.rsync_dict:
+                        sub_dirs = self.rsync_dict['sub-dirs']
+                        if len(sub_dirs) != len(sources):
+                            raise errs.ValidationError(f"ValidationError: if using " +
+                                "subdirs the number of subdirs must equal the number of sources")
+                        bp_with_subdir = os.path.join(bp, sub_dirs[i])
+                        if not os.path.exists(bp_with_subdir):
+                            os.makedirs(bp_with_subdir)
+                        source_and_target_args = [source, bp_with_subdir]
+
+                    args = source_and_target_args + additional_args
                     sub_utils.local_rsync_wrapper(args)
+
                 except errs.SubprocessError as e:
                     raise errs.SubprocessError( f"Error: rsync\n"
-                                                f"    from: {s}\n"
-                                                f"    to: {bp}\n"
+                                                f"    from: {source_and_target_args[0]}\n"
+                                                f"    to: {source_and_target_args[1]}\n"
                                               ) from e
         return 0
