restore_files() copies files from a backup location back to their
original paths, overwriting the current versions. By default, it creates a
new backup of the current files before overwriting, so the restore itself
can be undone.
restore_files_interactive() works the same way but shows a side-by-side
diff (powered by diffobj::diffFile()) for each file before asking whether
to restore it. This is useful when you want to review the difference between
the current version of the file and its backup.
The typical workflow is to call list_backups() or last_backup() to find
the backup you want, then pass the backup and original columns to
restore_files():
b <- last_backup()
restore_files(from = b$backup, to = b$original)Usage
restore_files(
from,
to,
...,
backup = TRUE,
description = NA_character_,
backup_dir = seekr_option("seekr.backup_dir"),
.progress = seekr_option("seekr.progress")
)
restore_files_interactive(
from,
to,
...,
backup = TRUE,
description = NA_character_,
backup_dir = seekr_option("seekr.backup_dir"),
.progress = seekr_option("seekr.progress")
)Arguments
- from
Character vector of source file paths to copy from. Typically the
backupcolumn oflist_backups()orlast_backup(). All files must exist.- to
Character vector of destination file paths to copy to. Typically the
originalcolumn oflist_backups()orlast_backup(). Must be the same length asfrom, with no duplicates. Destination files do not need to exist.- ...
For
restore_files(): these dots are for future extensions and must be empty.For
restore_files_interactive(): additional arguments passed todiffobj::diffFile(), allowing you to customize the diff display. For example,mode = "unified"switches to a unified diff format.- backup
Whether to create a backup of the current files before overwriting the files. Default is
TRUE. Set toFALSEto skip the backup, for example if the files are already tracked by another version control system.- description
Optional character string stored in the backup metadata when
backup = TRUE. Use it to describe why the backup was created. Defaults toNA.- backup_dir
Path to the backup directory. Defaults to
seekr_option("seekr.backup_dir"), which resolves to a platform-specific user data directory. Change the default globally withoptions(seekr.backup_dir = "/your/path").- .progress
Whether to display progress messages. Default is
TRUEin interactive sessions andFALSEotherwise (seerlang::is_interactive()). Can be set globally withoptions(seekr.progress = FALSE).
Value
Both functions invisibly return the to paths of the files that were
actually restored. For restore_files() this is always the full to
vector. For restore_files_interactive() this is only the subset of files
the user chose to restore, an empty character vector if the user cancelled
or skipped all files.
Interactive restore
restore_files_interactive() iterates over each file and shows a diff
between the backup (from) and the current version (to). For each file,
it prompts with the following choices:
Restore this file: restore this file and move to the next.
Ignore this file: skip this file and move to the next.
Restore all remaining files: restore this file and all subsequent ones without further prompts.
Ignore all remaining files: skip this file and all subsequent ones.
Cancel all planned changes: abort immediately without restoring anything, including files already confirmed in this session.
No files are modified until after the last prompt. All choices are
collected first, then applied in a single restore_files() call.
restore_files_interactive() requires the
diffobj package. It can only
be called in an interactive session.
See also
list_backups()andlast_backup()to find the backup you want to restore.delete_backups()to remove backups you no longer need.replace_files()which creates a backup before writing any changes.
Examples
# Set up a temporary project with two files
project_dir <- tempfile("seekr_project")
dir.create(project_dir)
backup_dir <- tempfile("seekr_backups")
dir.create(backup_dir)
file1 <- file.path(project_dir, "script1.R")
file2 <- file.path(project_dir, "script2.R")
writeLines("old_name <- function(x) x + 1", file1)
writeLines("y <- old_name(2)", file2)
# Search for the pattern we want to replace
x <- seekr("old_name", replacement = "new_name", path = project_dir)
x
#> <seekr::match[2]> 2 sources
#> Common Path: /tmp/RtmppsESWb/seekr_project19f5612f7ad7
#>
#> script1.R [1]
#> [1] -- 1 | old_name <- function(x) x + 1
#> ++ 1 | new_name <- function(x) x + 1
#>
#> script2.R [1]
#> [2] -- 1 | y <- old_name(2)
#> ++ 1 | y <- new_name(2)
#>
# No backup exists yet
list_backups(backup_dir = backup_dir)
#> # A tibble: 0 × 9
#> # ℹ 9 variables: id <int>, created_at <dttm>, operation <chr>,
#> # description <chr>, original <chr>, backup <chr>, original_exists <lgl>,
#> # backup_exists <lgl>, size <fs::bytes>
# Apply the replacement; a backup is created automatically
replace_files(x, backup_dir = backup_dir)
# The backup now contains the original (pre-replacement) version
# of both files, under id = 1
list_backups(backup_dir = backup_dir)
#> # A tibble: 2 × 9
#> id created_at operation description original backup
#> <int> <dttm> <chr> <chr> <chr> <chr>
#> 1 1 2026-07-11 20:15:06 replace NA /tmp/RtmppsESWb/seekr_… /tmp/…
#> 2 1 2026-07-11 20:15:06 replace NA /tmp/RtmppsESWb/seekr_… /tmp/…
#> # ℹ 3 more variables: original_exists <lgl>, backup_exists <lgl>,
#> # size <fs::bytes>
# The files on disk have changed
readLines(file1)
#> [1] "new_name <- function(x) x + 1"
readLines(file2)
#> [1] "y <- new_name(2)"
# Searching for the original pattern no longer finds anything
seekr("old_name", path = project_dir)
#> <seekr::match[0]> 0 sources
# Restore the files from the backup; this itself creates a second
# backup (id = 2) of the current (replaced) version, before overwriting
b <- last_backup(backup_dir = backup_dir)
restore_files(from = b$backup, to = b$original, backup_dir = backup_dir)
#> ℹ Creating a backup of the current version of each existing destination file
#> before restoring it.
#> ℹ This ensures you can revert to the state before restoration if needed.
# We now have two backups: id = 1 is the state before replace_files(),
# id = 2 is the state before restore_files() (i.e. the replaced version)
list_backups(backup_dir = backup_dir)
#> # A tibble: 4 × 9
#> id created_at operation description original backup
#> <int> <dttm> <chr> <chr> <chr> <chr>
#> 1 2 2026-07-11 20:15:06 restore NA /tmp/RtmppsESWb/seekr_… /tmp/…
#> 2 2 2026-07-11 20:15:06 restore NA /tmp/RtmppsESWb/seekr_… /tmp/…
#> 3 1 2026-07-11 20:15:06 replace NA /tmp/RtmppsESWb/seekr_… /tmp/…
#> 4 1 2026-07-11 20:15:06 replace NA /tmp/RtmppsESWb/seekr_… /tmp/…
#> # ℹ 3 more variables: original_exists <lgl>, backup_exists <lgl>,
#> # size <fs::bytes>
# The files are back to their original content
readLines(file1)
#> [1] "old_name <- function(x) x + 1"
readLines(file2)
#> [1] "y <- old_name(2)"
# The original pattern is found again
seekr("old_name", path = project_dir)
#> <seekr::match[2]> 2 sources
#> Common Path: /tmp/RtmppsESWb/seekr_project19f5612f7ad7
#>
#> script1.R [1]
#> [1] -> 1 | old_name <- function(x) x + 1
#>
#> script2.R [1]
#> [2] -> 1 | y <- old_name(2)
#>
if (FALSE) { # \dontrun{
# open_backup_dir() opens a file browser, so it is not run here
open_backup_dir()
# Review each file interactively before restoring
restore_files_interactive(from = b$backup, to = b$original)
# Customize the diff display (unified format)
restore_files_interactive(
from = b$backup,
to = b$original,
mode = "unified",
color.mode = "yb"
)
# Finally, particular backups in a backup_dir can be deleted
b <- list_backups(backup_dir = backup_dir)
b
delete_backups(id = b$id, backup_dir = backup_dir)
} # }
unlink(project_dir, recursive = TRUE)
unlink(backup_dir, recursive = TRUE)
