R/directory_access.R

Defines functions print.directory_access_result directory.access

Documented in directory.access

#' Check Whether Path is a Directory
#'
#' Validates whether a directory exists and checks its read/write
#' access along with content counts. Supports both local and UNC
#' network paths.
#'
#' @param path Character string. Directory path to validate.
#'
#' @return A list of class \code{directory_access_result} containing:
#' \itemize{
#'   \item path - Normalized directory path
#'   \item exists - TRUE/FALSE
#'   \item readable - TRUE/FALSE
#'   \item writable - TRUE/FALSE
#'   \item file_count - Number of files in directory
#'   \item folder_count - Number of subdirectories
#'   \item empty - TRUE/FALSE
#'   \item status - Overall status message
#' }
#'
#' @examples
#' # Check a temporary directory
#' result <- directory.access(tempdir())
#' print(result)
#'
#' # Check a path that does not exist
#' result <- directory.access(
#'   file.path(tempdir(), "no_such_folder")
#' )
#' print(result)
#'
#' \donttest{
#' # UNC network path (requires network access)
#' directory.access("//server/share/project")
#' }
#'
#' @export
directory.access <- function(path) {
  if (!is.character(path) || length(path) != 1 || is.na(path)) {
    stop("path must be a non-empty character string")
  }

  is_unc <- grepl("^[/\\\\]{2}", path)
  path_norm <- if (is_unc) {
    path
  } else {
    tryCatch(
      normalizePath(path, winslash = "/", mustWork = FALSE),
      error = function(e) path
    )
  }

  result <- list(
    path         = path_norm,
    exists       = FALSE,
    readable     = FALSE,
    writable     = FALSE,
    file_count   = NA_integer_,
    folder_count = NA_integer_,
    empty        = NA,
    status       = "Directory not found"
  )

  exists        <- dir.exists(path_norm)
  result$exists <- exists

  if (!exists) {
    class(result) <- "directory_access_result"
    return(result)
  }

  readable <- tryCatch({
    list.files(path_norm)
    TRUE
  }, error = function(e) FALSE)

  writable <- tryCatch({
    test_file <- tempfile(tmpdir = path_norm)
    con <- file(test_file, open = "w")
    close(con)
    unlink(test_file)
    TRUE
  }, error = function(e) FALSE)

  files <- tryCatch({
    list.files(path_norm, recursive = FALSE, full.names = TRUE)
  }, error = function(e) character(0))

  file_count   <- sum(file.info(files)$isdir == FALSE, na.rm = TRUE)
  folder_count <- sum(file.info(files)$isdir == TRUE,  na.rm = TRUE)

  result$readable     <- readable
  result$writable     <- writable
  result$file_count   <- file_count
  result$folder_count <- folder_count
  result$empty        <- (file_count + folder_count) == 0
  result$status       <- ifelse(
    readable && writable, "Directory accessible",
    ifelse(readable, "Read-only directory", "Directory not accessible")
  )

  class(result) <- "directory_access_result"
  return(result)
}

#' @export
print.directory_access_result <- function(x, ...) {
  cat("\n")
  cat("========================================\n")
  cat("DIRECTORY ACCESS REPORT\n")
  cat("========================================\n\n")
  cat("Path         :", x$path,         "\n")
  cat("Exists       :", x$exists,       "\n")
  cat("Readable     :", x$readable,     "\n")
  cat("Writable     :", x$writable,     "\n")
  cat("Files        :", x$file_count,   "\n")
  cat("Folders      :", x$folder_count, "\n")
  cat("Empty        :", x$empty,        "\n")
  cat("Status       :", x$status,       "\n")
  cat("\n========================================\n")
  invisible(x)
}

Try the fileaccess package in your browser

Any scripts or data that you put into this service are public.

fileaccess documentation built on June 18, 2026, 1:06 a.m.