public static async Task Sync(string csA, string csB, StringPath pathA, StringPath pathB, int parallel, ILogger log)
        {
            pathB = pathB ?? pathA;

            var storeA = new AzureBlobFileStore(csA, pathA);
            var storeB = new AzureBlobFileStore(csB, pathB);

            log.Information("Starting async {FromEndpoint} ({FromPath}) > {ToEndpoint} ({ToPath})",
                            storeA.Storage.BlobEndpoint, storeA.BasePath, storeB.Storage.BlobEndpoint, storeB.BasePath);

            await SyncDirectory(pathA, pathB, parallel, log, storeA, storeB);
        }
        static async Task SyncDirectory(StringPath pathA, StringPath pathB, int parallel, ILogger log, AzureBlobFileStore storeA, AzureBlobFileStore storeB)
        {
            var sw = Stopwatch.StartNew();

            var filesATask = storeA.List(allDirectories: true).ToListWithAction(b => log.Debug("Listed {Files} from source {Path}", b, pathA));
            var filesBTask = storeB.List(allDirectories: true).ToListWithAction(b => log.Debug("Listed {Files} from destination {Path}", b, pathB));

            var filesA = (await filesATask).ToDictionary(f => f.Path);
            var filesB = (await filesBTask).ToDictionary(f => f.Path);

            log.Information("Listed all files {Source} souce {Dest} dest in {Duration}",
                            filesA.Count, filesB.Count, sw.Elapsed.Humanize(2));

            var toCreate = filesA.Values.Where(f => !filesB.ContainsKey(f.Path)).ToList();
            var toUpdate = filesA.Values.Where(f => filesB.TryGet(f.Path)?.Modified < f.Modified).ToList();

            async Task <IReadOnlyCollection <StringPath> > SaveAll(IEnumerable <FileListItem> files, string action) =>
            await files.BlockTransform(async f => {
                using (var content = await storeA.Load(f.Path))
                    await storeB.Save(f.Path, content);
                return(f.Path);
            },
                                       parallel,
                                       progressUpdate : p => log.Debug("{Action} {Files} at {Speed}", action, p.CompletedTotal, p.Speed("files")));

            sw.Restart();
            log.Information("Starting sync. {Update} to update, {Create} to create",
                            toCreate.Count, toUpdate.Count);

            var created = await SaveAll(toCreate, "Created");

            var updated = await SaveAll(toUpdate, "Updated");

            log.Information("Completed sync. {Updated} updated, {Created} created in {Duration}",
                            updated.Count, created.Count, sw.Elapsed.Humanize(2));
        }