{syncdr} is an R package for handling and synchronizing files and directories. Its primary objectives are:
π‘
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.
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
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:
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 |
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 |
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
# 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>
# 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>
# 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>
verbose = TRUEWhen 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>
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)
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:
by_date = TRUE): Copy files that are
newer in the left directory to the right directory.by_date = TRUE and
by_content = TRUE): Copy files that are newer and different
in the left directory to the right directory.by_content = TRUE): Copy files that
are different in the left directory to the right directory.
# Compare directories
sync_status <- compare_directories(left,
right,
by_date = TRUE)
# Synchronize directories
full_asym_sync_to_right(sync_status = sync_status)
#> β synchronized