Last active
July 4, 2017 04:23
-
-
Save r2evans/755bd663f87ff75a5aaf4397973206bb to your computer and use it in GitHub Desktop.
numbered filenames, "guaranteed" to produce a unique and sequential filename
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#' Sequential file naming | |
#' | |
#' (https://stackoverflow.com/a/44868545/3358272) | |
#' | |
#' @param ptn string that includes a [base::sprintf()] format string for an | |
#' integer, either `%d` or `%03d`; for example, `"filename-%03d.pdf"` | |
#' @param full.names logical, passed to [base::files()] | |
#' @return character, representing a filename that did not exist the | |
#' moment the function was called; NB: there is a potential | |
#' race-condition here | |
#' @md | |
#' @example | |
#' \dontrun{ | |
#' ### starts at 1 for non-existent files | |
#' sequentialFilename("does-not-yet-exist-%d.pdf") | |
#' # [1] "does-not-yet-exist-1.pdf" | |
#' sequentialFilename("does-not-yet-exist-%05d.pdf") | |
#' # [1] "does-not-yet-exist-00001.pdf" | |
#' | |
#' ### empty files, please do not blame me if you over-write pre-existing files! | |
#' writeLines("", "fn-001") | |
#' writeLines("", "fn-002") | |
#' sequentialFilename("fn-%03d") | |
#' # [1] "fn-003" | |
#' | |
#' ### finds the max, not the next unused | |
#' writeLines("", "fn-100") | |
#' sequentialFilename("fn-%03d") | |
#' # [1] "fn-101" | |
#' | |
#' ### can extend beyond the patterned number | |
#' writeLines("", "fn-1000") | |
#' sequentialFilename("fn-%03d") | |
#' # [1] "fn-1001" | |
#' } | |
sequentialFilename <- function(ptn, full.names = FALSE) { | |
if (! nchar(gsub("[^%]", "", ptn)) == 1L || | |
! grepl("%[0-9]*d", ptn)) | |
stop("'ptn' must contain exactly one '%' sprintf formatting string") | |
# extract the numbering portion, to convert into a filename glob | |
gre <- gregexpr("%[0-9]*d", ptn) | |
# escape globbing characters | |
glob <- gsub("([.*?])", "\\\\\\1", ptn) | |
regmatches(glob, gre) <- "[0-9]+" | |
files <- list.files(pattern = glob, full.names = full.names) | |
# find the highest used numbered filename | |
highestnumber <- | |
if (! length(files)) { | |
0 | |
} else { | |
prepost <- regmatches(ptn, gre, invert = TRUE)[[1L]] | |
max(as.integer( | |
mapply(substr, files, | |
1 + nchar(prepost[1]), nchar(files) - nchar(prepost[2])) | |
), 0, na.rm = TRUE) | |
} | |
if (is.na(highestnumber)) | |
stop("something went wrong, could not find the next number") | |
nextfile <- sprintf(ptn, highestnumber + 1) | |
browser() | |
if (file.exists(nextfile)) | |
stop(paste("oops, the next-numbered file already exists ...", | |
sQuote(nextfile)), call. = FALSE) | |
nextfile | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment