/// <summary>
        /// Deletes any directories in the target directory that are not listed in source array.
        /// </summary>
        private void DeleteSourceDirectoriesFromTarget(DirectoryInfo[] sourceDirectories, DirectoryInfo targetDirInfo)
        {
            // Get current target directories
            DirectoryInfo[] targetDirectories = targetDirInfo.EnumerateDirectories("*", SearchOption.TopDirectoryOnly).ToArray();

            // Need to check for directories that exist in target but not in source
            foreach (DirectoryInfo target in targetDirectories)
            {
                // Only sub-dir name will match (ignore case), full paths are from different locations
                bool remove = !sourceDirectories.Any(source => string.Compare(source.Name, target.Name, true) == 0);

                // Remove if directory is now excluded, but not overridden by a source
                remove |= BackupSettings.IsDirectoryExcluded(target.Name) && !sourceDirsInTarget.Any(s => s.StartsWith(target.FullName, StringComparison.OrdinalIgnoreCase));

                // Remove if hidden options changed
                remove |= BackupSettings.IgnoreHiddenFiles && (target.Attributes & FileAttributes.Hidden) > 0;

                if (remove)
                {
                    DeleteDirectory(target);
                }
            }
        }
        /// <summary>
        /// Copies directory from source to target.
        /// </summary>
        /// <param name="sourceDirInfo">Source directory to copy</param>
        /// <param name="targetDirInfo">Target directory where backup is to take place</param>
        /// <returns>Number of files backed up</returns>
        protected int CopyFiles(DirectoryInfo sourceDirInfo, DirectoryInfo targetDirInfo)
        {
            int backupCount = 0;

            // Check source exists and whether hidden should be backup up.
            // (Files within a hidden directory are also considered hidden.)
            if (!BackupSettings.IgnoreHiddenFiles || (sourceDirInfo.Attributes & FileAttributes.Hidden) == 0)
            {
                // Remove common root path
                string sourceSubDir = GetSourceSubDir(sourceDirInfo.FullName, targetDirInfo.FullName);

                // Get target path
                string targetDir = Path.Combine(targetDirInfo.FullName, sourceSubDir);

                // Get qualifying files only
                var files = Directory.EnumerateFiles(sourceDirInfo.FullName, "*.*", SearchOption.TopDirectoryOnly).Where(f => !BackupSettings.IsFileTypeExcluded(f));

                // Copy files in current directory
                backupCount = CopyFiles(files, targetDir);

                // Recursive call for sub directories
                foreach (DirectoryInfo subDirInfo in sourceDirInfo.EnumerateDirectories("*", SearchOption.TopDirectoryOnly).Where(d => !BackupSettings.IsDirectoryExcluded(d.Name)))
                {
                    backupCount += CopyFiles(subDirInfo, targetDirInfo);
                }
            }

            return(backupCount);
        }
        /// <summary>
        /// Remove directories/files from target that are not in source,
        /// then copies in new/updated files.
        /// </summary>
        private int SyncDirectories(string sourceDir, string targetDir)
        {
            DirectoryInfo sourceDirInfo = new(sourceDir);
            DirectoryInfo targetDirInfo = new(targetDir);

            // Get qualifying files only
            var sourceFiles = Directory.EnumerateFiles(sourceDirInfo.FullName, "*.*", SearchOption.TopDirectoryOnly).Where(f => !BackupSettings.IsFileTypeExcluded(f));

            // Check if previous backup taken place
            if (targetDirInfo.Exists)
            {
                //////////////////////////////////////////////////////
                // Remove directories from target not in source
                // (Remove before copying new files to free up space)
                //////////////////////////////////////////////////////
                DeleteSourceDirectoriesFromTarget(sourceDirInfo, targetDirInfo);

                //////////////////////////////////////////////////////
                // Remove files from target not in source
                // (Remove before copying new files to free up space)
                //////////////////////////////////////////////////////
                DeleteSourceFilesFromTarget(sourceFiles, targetDirInfo);
            }

            int backupCount = 0;

            // Check whether backing up hidden directories
            if (!BackupSettings.IgnoreHiddenFiles || (sourceDirInfo.Attributes & FileAttributes.Hidden) == 0)
            {
                //////////////////////////////////////////////////////
                // Copy files from source not in target
                // (Or replace old files)
                //////////////////////////////////////////////////////
                backupCount = CopyFiles(sourceFiles, targetDir);

                /////////////////////////////////////////////
                // Sync sub directories
                /////////////////////////////////////////////
                foreach (DirectoryInfo subDirInfo in sourceDirInfo.EnumerateDirectories("*", SearchOption.TopDirectoryOnly).Where(d => !BackupSettings.IsDirectoryExcluded(d.Name)))
                {
                    // Get sub-directories
                    string subSourceDir = Path.Combine(sourceDir, subDirInfo.Name);
                    string subTargetDir = Path.Combine(targetDir, subDirInfo.Name);

                    // Recursive call
                    backupCount += SyncDirectories(subSourceDir, subTargetDir);
                }
            }

            return(backupCount);
        }