The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Why {syncdr}?

{syncdr} is an R package for handling and synchronizing files and directories. Its primary objectives are:

  1. To provide a clear snapshot of the content and status of synchronization between two directories under comparison: including their tree structure, their common files, and files that are exclusive to either directory
  2. To make file organization and management in R easier: i.e., enabling content-based and modification date-based file comparisons, as well as facilitating tasks such as duplicates identification, file copying, moving, and deletion.

πŸ’‘
This article does not offer a comprehensive overview of {syncdr} functionalities. Rather it provides a sample workflow for working with the package’s main functions . After familiarizing yourself with this general workflow, read the articles throughout the rest of this website -they will explore all features of {syncdr} in a structured way.


Synchronizing with {syncdr}

Learn how to work with {syncdr} and compare and synchronize directories in R

Suppose you are working with two directories, let’s call them left and right -each containing certain files and folders/sub-folders.

Let’s first call syncdr function toy_dirs(). This generates two toy directories in .syncdrenv environment -say left and right- that we can use to showcase syncdr functionalities.


# Create syncdr env with left and right directories
.syncdrenv =toy_dirs()
#> β– β– β– β– β– β– β– β– β–                          27% | ETA:  9s
#> β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β– β–                  53% | ETA:  6s

# Get left and right directories' paths 
left  <- .syncdrenv$left
right <- .syncdrenv$right

You can start by quickly comparing the two directories’ tree structure by calling display_dir_tree(). By default, it fully recurses -i.e., shows the directory tree of all sub-directories. However, you can also specify the number of levels to recurse using the recurse argument.


# Visualize left and right directories' tree structure 
display_dir_tree(path_left  = left,
                 path_right = right)
#> (←)Left directory structure:
#> C:/Users/wb621604/AppData/Local/Temp/Rtmpmg13ZH/left
#> β”œβ”€β”€ A
#> β”‚   β”œβ”€β”€ A1.Rds
#> β”‚   β”œβ”€β”€ A2.Rds
#> β”‚   └── A3.Rds
#> β”œβ”€β”€ B
#> β”‚   β”œβ”€β”€ B1.Rds
#> β”‚   β”œβ”€β”€ B2.Rds
#> β”‚   └── B3.Rds
#> β”œβ”€β”€ C
#> β”‚   β”œβ”€β”€ C1.Rds
#> β”‚   β”œβ”€β”€ C1_duplicate.Rds
#> β”‚   β”œβ”€β”€ C2.Rds
#> β”‚   └── C3.Rds
#> β”œβ”€β”€ D
#> β”‚   β”œβ”€β”€ D1.Rds
#> β”‚   β”œβ”€β”€ D2.Rds
#> β”‚   └── D3.Rds
#> └── E
#>     β”œβ”€β”€ E1.Rds
#>     β”œβ”€β”€ E2.Rds
#>     └── E3.Rds
#> (β†’)Right directory structure:
#> C:/Users/wb621604/AppData/Local/Temp/Rtmpmg13ZH/right
#> β”œβ”€β”€ A
#> β”‚   β”œβ”€β”€ A1.Rds
#> β”‚   β”œβ”€β”€ A2.Rds
#> β”‚   └── A3.Rds
#> β”œβ”€β”€ B
#> β”‚   β”œβ”€β”€ B1.Rds
#> β”‚   β”œβ”€β”€ B2.Rds
#> β”‚   └── B3.Rds
#> β”œβ”€β”€ C
#> β”‚   β”œβ”€β”€ C1.Rds
#> β”‚   β”œβ”€β”€ C1_duplicate.Rds
#> β”‚   β”œβ”€β”€ C2.Rds
#> β”‚   └── C3.Rds
#> β”œβ”€β”€ D
#> β”‚   β”œβ”€β”€ D1.Rds
#> β”‚   β”œβ”€β”€ D2.Rds
#> β”‚   └── D3.Rds
#> └── E
#>     β”œβ”€β”€ E1.Rds
#>     β”œβ”€β”€ E2.Rds
#>     └── E3.Rds

Step 1: Compare Directories

The most important function in syncdr is compare_directories(). It takes the paths of left and right directories and compares them to determine their synchronization status (see below). This function represents the backbone of syncdr: you can utilize the syncdr_status object it generates both:

  • to inspect the synchronization status of files present in both directories as well as those exclusive to either directory

  • as the input for all other functions within syncdr that allow synchronization between the directories under comparison.

Before diving into the resulting syncdr_status object, note that compare_directories() enables to compare directories in 3 ways:

  1. By date only -the default: by default, by_date = TRUE, so that files in both directories are compared based on the date of last modification.
sync_status (all common files)
older in left, newer in right dir
newer in left, olderin right dir
same date
  1. By date and content. This is done by specifying by_content = TRUE (by default by_date = TRUE if not specifically set to FALSE). Files are first compared by date, and then only those that are newer in either directory will be compared by content.
sync_status (common files that are newer in either left or right, i.e., not of same date )
different content
same content
  1. By content only, by specifying by_date = FALSE and by_content = TRUE . This option is however discouraged -comparing all files’ contents can be slow and computationally expensive.
sync_status (all common files)
different content
same content

Also, regardless of which options you choose, the sync_status of files that are exclusive to either directory is determined as:

sync_status (non common files)
only in left
only in right

Let’s now take a closer look at the output of compare_directories(), which is intended to contain comprehensive information on the directories under comparison. This is a list of class syncdr_status, containing 4 elements: (1) common files, (2) non common files, (3) left path and (4) right path

1. Comparing by date

# Compare by date only -the Default
sync_status_date <- compare_directories(left, 
                                        right)

sync_status_date
#> 
#> ── Synchronization Summary ─────────────────────────────────────────────────────
#> β€’ Left Directory: 'C:/Users/wb621604/AppData/Local/Temp/Rtmpmg13ZH/left'
#> β€’ Right Directory: 'C:/Users/wb621604/AppData/Local/Temp/Rtmpmg13ZH/right'
#> β€’ Total Common Files: 16
#> β€’ Total Non-common Files: 0
#> β€’ Compare files by: date
#> 
#> ── Common files ────────────────────────────────────────────────────────────────
#>                        path modification_time_left modification_time_right
#> 1            /left/A/A1.Rds    2026-01-23 16:57:04     2026-01-23 16:56:54
#> 2            /left/A/A2.Rds    2026-01-23 16:57:07     2026-01-23 16:56:57
#> 3            /left/A/A3.Rds    2026-01-23 16:57:10     2026-01-23 16:57:00
#> 4            /left/B/B1.Rds    2026-01-23 16:57:04     2026-01-23 16:57:05
#> 5            /left/B/B2.Rds    2026-01-23 16:57:07     2026-01-23 16:57:08
#> 6            /left/B/B3.Rds    2026-01-23 16:57:10     2026-01-23 16:57:00
#> 7            /left/C/C1.Rds    2026-01-23 16:57:05     2026-01-23 16:57:05
#> 8  /left/C/C1_duplicate.Rds    2026-01-23 16:57:05     2026-01-23 16:56:55
#> 9            /left/C/C2.Rds    2026-01-23 16:57:08     2026-01-23 16:57:09
#> 10           /left/C/C3.Rds    2026-01-23 16:57:10     2026-01-23 16:57:11
#> 11           /left/D/D1.Rds    2026-01-23 16:57:07     2026-01-23 16:57:06
#> 12           /left/D/D2.Rds    2026-01-23 16:57:10     2026-01-23 16:57:09
#> 13           /left/D/D3.Rds    2026-01-23 16:57:01     2026-01-23 16:57:11
#> 14           /left/E/E1.Rds    2026-01-23 16:56:57     2026-01-23 16:57:07
#> 15           /left/E/E2.Rds    2026-01-23 16:57:00     2026-01-23 16:57:10
#> 16           /left/E/E3.Rds    2026-01-23 16:57:01     2026-01-23 16:57:11
#>     modified
#> 1       left
#> 2       left
#> 3       left
#> 4      right
#> 5      right
#> 6       left
#> 7  same date
#> 8       left
#> 9      right
#> 10     right
#> 11      left
#> 12      left
#> 13     right
#> 14     right
#> 15     right
#> 16     right
#> 
#> ── Non-common files ────────────────────────────────────────────────────────────
#> 
#> ── Only in left ──
#> 
#> # A tibble: 0 Γ— 1
#> # β„Ή 1 variable: path_left <fs::path>
#> ── Only in right ──
#> # A tibble: 0 Γ— 1
#> # β„Ή 1 variable: path_right <fs::path>
2. Comparing by date and content

# Compare by date and content 
sync_status_date_content <- compare_directories(left, 
                                                right,
                                                by_content = TRUE)

sync_status_date_content
#> 
#> ── Synchronization Summary ─────────────────────────────────────────────────────
#> β€’ Left Directory: 'C:/Users/wb621604/AppData/Local/Temp/Rtmpmg13ZH/left'
#> β€’ Right Directory: 'C:/Users/wb621604/AppData/Local/Temp/Rtmpmg13ZH/right'
#> β€’ Total Common Files: 15
#> β€’ Total Non-common Files: 0
#> β€’ Compare files by: date & content
#> 
#> ── Common files ────────────────────────────────────────────────────────────────
#>                        path modification_time_left modification_time_right
#> 1            /left/A/A1.Rds    2026-01-23 16:57:04     2026-01-23 16:56:54
#> 2            /left/A/A2.Rds    2026-01-23 16:57:07     2026-01-23 16:56:57
#> 3            /left/A/A3.Rds    2026-01-23 16:57:10     2026-01-23 16:57:00
#> 4            /left/B/B1.Rds    2026-01-23 16:57:04     2026-01-23 16:57:05
#> 5            /left/B/B2.Rds    2026-01-23 16:57:07     2026-01-23 16:57:08
#> 6            /left/B/B3.Rds    2026-01-23 16:57:10     2026-01-23 16:57:00
#> 7  /left/C/C1_duplicate.Rds    2026-01-23 16:57:05     2026-01-23 16:56:55
#> 8            /left/C/C2.Rds    2026-01-23 16:57:08     2026-01-23 16:57:09
#> 9            /left/C/C3.Rds    2026-01-23 16:57:10     2026-01-23 16:57:11
#> 10           /left/D/D1.Rds    2026-01-23 16:57:07     2026-01-23 16:57:06
#> 11           /left/D/D2.Rds    2026-01-23 16:57:10     2026-01-23 16:57:09
#> 12           /left/D/D3.Rds    2026-01-23 16:57:01     2026-01-23 16:57:11
#> 13           /left/E/E1.Rds    2026-01-23 16:56:57     2026-01-23 16:57:07
#> 14           /left/E/E2.Rds    2026-01-23 16:57:00     2026-01-23 16:57:10
#> 15           /left/E/E3.Rds    2026-01-23 16:57:01     2026-01-23 16:57:11
#>    modified       sync_status
#> 1      left different content
#> 2      left different content
#> 3      left different content
#> 4     right different content
#> 5     right different content
#> 6      left different content
#> 7      left different content
#> 8     right different content
#> 9     right different content
#> 10     left different content
#> 11     left different content
#> 12    right different content
#> 13    right different content
#> 14    right different content
#> 15    right different content
#> 
#> ── Non-common files ────────────────────────────────────────────────────────────
#> 
#> ── Only in left ──
#> 
#> # A tibble: 0 Γ— 1
#> # β„Ή 1 variable: path_left <fs::path>
#> ── Only in right ──
#> # A tibble: 0 Γ— 1
#> # β„Ή 1 variable: path_right <fs::path>
3. Comparing by content only

# Compare by date and content 
sync_status_content <- compare_directories(left, 
                                            right,
                                            by_date    = FALSE,
                                            by_content = TRUE)

sync_status_content
#> 
#> ── Synchronization Summary ─────────────────────────────────────────────────────
#> β€’ Left Directory: 'C:/Users/wb621604/AppData/Local/Temp/Rtmpmg13ZH/left'
#> β€’ Right Directory: 'C:/Users/wb621604/AppData/Local/Temp/Rtmpmg13ZH/right'
#> β€’ Total Common Files: 16
#> β€’ Total Non-common Files: 0
#> β€’ Compare files by: content
#> 
#> ── Common files ────────────────────────────────────────────────────────────────
#>                        path       sync_status
#> 1            /left/A/A1.Rds different content
#> 2            /left/A/A2.Rds different content
#> 3            /left/A/A3.Rds different content
#> 4            /left/B/B1.Rds different content
#> 5            /left/B/B2.Rds different content
#> 6            /left/B/B3.Rds different content
#> 7            /left/C/C1.Rds      same content
#> 8  /left/C/C1_duplicate.Rds different content
#> 9            /left/C/C2.Rds different content
#> 10           /left/C/C3.Rds different content
#> 11           /left/D/D1.Rds different content
#> 12           /left/D/D2.Rds different content
#> 13           /left/D/D3.Rds different content
#> 14           /left/E/E1.Rds different content
#> 15           /left/E/E2.Rds different content
#> 16           /left/E/E3.Rds different content
#> 
#> ── Non-common files ────────────────────────────────────────────────────────────
#> 
#> ── Only in left ──
#> 
#> # A tibble: 0 Γ— 1
#> # β„Ή 1 variable: path_left <fs::path>
#> ── Only in right ──
#> # A tibble: 0 Γ— 1
#> # β„Ή 1 variable: path_right <fs::path>
*️⃣ Comparing directories with verbose = TRUE

When calling compare_directories(), you have the option to enable verbose mode by setting verbose = TRUE. This will display both directories tree structure and, when comparing files by content, provide progress updates including the time spent hashing the files.


compare_directories(left,
                    right,
                    by_date    = FALSE,
                    by_content = TRUE,
                    verbose    = TRUE)
#> β ™ cli-159588-449
#> βœ” A1.Rds [5ms]
#> 
#> β ™ cli-159588-449
#> βœ” A2.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” A3.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” B1.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” B2.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” B3.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” C1.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” C1_duplicate.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” C2.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” C3.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” D1.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” D2.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” D3.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” E1.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” E2.Rds [4ms]
#> 
#> β ™ cli-159588-449
#> βœ” E3.Rds [4ms]
#> 
#> ── Hashing completed! Total time spent: 0.1604221 secs ──
#> 
#> β ™ cli-159588-549
#> βœ” A1.Rds [4ms]
#> 
#> β ™ cli-159588-549
#> βœ” A2.Rds [4ms]
#> 
#> β ™ cli-159588-549
#> βœ” A3.Rds [5ms]
#> 
#> β ™ cli-159588-549
#> βœ” B1.Rds [4ms]
#> 
#> β ™ cli-159588-549
#> βœ” B2.Rds [7ms]
#> 
#> β ™ cli-159588-549
#> βœ” B3.Rds [5ms]
#> 
#> β ™ cli-159588-549
#> βœ” C1.Rds [4ms]
#> 
#> β ™ cli-159588-549
#> βœ” C1_duplicate.Rds [4ms]
#> 
#> β ™ cli-159588-549
#> βœ” C2.Rds [4ms]
#> 
#> β ™ cli-159588-549
#> βœ” C3.Rds [4ms]
#> 
#> β ™ cli-159588-549
#> βœ” D1.Rds [4ms]
#> 
#> β ™ cli-159588-549
#> βœ” D2.Rds [4ms]
#> 
#> β ™ cli-159588-549
#> βœ” D3.Rds [4ms]
#> 
#> β ™ cli-159588-549
#> βœ” E1.Rds [4ms]
#> 
#> β ™ cli-159588-549
#> βœ” E2.Rds [4ms]
#> 
#> β ™ cli-159588-549
#> βœ” E3.Rds [4ms]
#> 
#> ── Hashing completed! Total time spent: 0.152535 secs ──
#> 
#> (←)Left directory structure:
#> C:/Users/wb621604/AppData/Local/Temp/Rtmpmg13ZH/left
#> β”œβ”€β”€ A
#> β”‚   β”œβ”€β”€ A1.Rds
#> β”‚   β”œβ”€β”€ A2.Rds
#> β”‚   └── A3.Rds
#> β”œβ”€β”€ B
#> β”‚   β”œβ”€β”€ B1.Rds
#> β”‚   β”œβ”€β”€ B2.Rds
#> β”‚   └── B3.Rds
#> β”œβ”€β”€ C
#> β”‚   β”œβ”€β”€ C1.Rds
#> β”‚   β”œβ”€β”€ C1_duplicate.Rds
#> β”‚   β”œβ”€β”€ C2.Rds
#> β”‚   └── C3.Rds
#> β”œβ”€β”€ D
#> β”‚   β”œβ”€β”€ D1.Rds
#> β”‚   β”œβ”€β”€ D2.Rds
#> β”‚   └── D3.Rds
#> └── E
#>     β”œβ”€β”€ E1.Rds
#>     β”œβ”€β”€ E2.Rds
#>     └── E3.Rds
#> (β†’)Right directory structure:
#> C:/Users/wb621604/AppData/Local/Temp/Rtmpmg13ZH/right
#> β”œβ”€β”€ A
#> β”‚   β”œβ”€β”€ A1.Rds
#> β”‚   β”œβ”€β”€ A2.Rds
#> β”‚   └── A3.Rds
#> β”œβ”€β”€ B
#> β”‚   β”œβ”€β”€ B1.Rds
#> β”‚   β”œβ”€β”€ B2.Rds
#> β”‚   └── B3.Rds
#> β”œβ”€β”€ C
#> β”‚   β”œβ”€β”€ C1.Rds
#> β”‚   β”œβ”€β”€ C1_duplicate.Rds
#> β”‚   β”œβ”€β”€ C2.Rds
#> β”‚   └── C3.Rds
#> β”œβ”€β”€ D
#> β”‚   β”œβ”€β”€ D1.Rds
#> β”‚   β”œβ”€β”€ D2.Rds
#> β”‚   └── D3.Rds
#> └── E
#>     β”œβ”€β”€ E1.Rds
#>     β”œβ”€β”€ E2.Rds
#>     └── E3.Rds
#> ── Synchronization Summary ─────────────────────────────────────────────────────
#> β€’ Left Directory: 'C:/Users/wb621604/AppData/Local/Temp/Rtmpmg13ZH/left'
#> β€’ Right Directory: 'C:/Users/wb621604/AppData/Local/Temp/Rtmpmg13ZH/right'
#> β€’ Total Common Files: 16
#> β€’ Total Non-common Files: 0
#> β€’ Compare files by: content
#> 
#> ── Common files ────────────────────────────────────────────────────────────────
#>                        path       sync_status
#> 1            /left/A/A1.Rds different content
#> 2            /left/A/A2.Rds different content
#> 3            /left/A/A3.Rds different content
#> 4            /left/B/B1.Rds different content
#> 5            /left/B/B2.Rds different content
#> 6            /left/B/B3.Rds different content
#> 7            /left/C/C1.Rds      same content
#> 8  /left/C/C1_duplicate.Rds different content
#> 9            /left/C/C2.Rds different content
#> 10           /left/C/C3.Rds different content
#> 11           /left/D/D1.Rds different content
#> 12           /left/D/D2.Rds different content
#> 13           /left/D/D3.Rds different content
#> 14           /left/E/E1.Rds different content
#> 15           /left/E/E2.Rds different content
#> 16           /left/E/E3.Rds different content
#> 
#> ── Non-common files ────────────────────────────────────────────────────────────
#> 
#> ── Only in left ──
#> 
#> # A tibble: 0 Γ— 1
#> # β„Ή 1 variable: path_left <fs::path>
#> ── Only in right ──
#> # A tibble: 0 Γ— 1
#> # β„Ή 1 variable: path_right <fs::path>

Step 2: Visualize Synchronization Status

The best way to read through the output of compare_directories() is by visualizing it with display_sync_status() function.

For example, let’s visualize the sync status of common files in left and right directories, when compared by date


display_sync_status(sync_status_date$common_files,
                    left_path  = left,
                    right_path = right)

or let’s display the sync status of non common files:


display_sync_status(sync_status_date$non_common_files,
                    left_path  = left,
                    right_path = right)

Step 3: Synchronize directories

syncdr enables users to perform different actions such as copying, moving, and deleting files using specific synchronization functions. Refer to the vignette("asymmetric-synchronization") and vignette("symmetric-synchronization") articles for detailed information.

For the purpose of this general demonstration, we will perform a β€˜full asymmetric synchronization to right’. This specific function executes the following:

  • On common files:
    • If by date only (by_date = TRUE): Copy files that are newer in the left directory to the right directory.
    • If by date and content (by_date = TRUE and by_content = TRUE): Copy files that are newer and different in the left directory to the right directory.
    • If by content only (by_content = TRUE): Copy files that are different in the left directory to the right directory.
  • On non common files:
    • Copy to the right directory those files that exist only in the left directory
    • Delete from the right directory those files that are exclusive in the right directory (i.e., missing in the left directory)

# Compare directories

sync_status <- compare_directories(left,
                                   right,
                                   by_date = TRUE)

# Synchronize directories 
full_asym_sync_to_right(sync_status = sync_status)
#> βœ” synchronized

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.