Batch renaming files in subfolder of working directory to sequence

84 views Asked by At

There are similar questions on Stack Overflow but none quite meets my specific needs.

I have a list of files with random names in a subfolder of my working directory, e.g. working_directory/animals/photos

The files are currently named:

Chicken.png
Moose.png
Cat.png

And I would like to rename them into the following (I have 5750 photos):

Animal1.png
Animal2.png
Animal3.png
...
Animal5750.png

I feel like there should be a simple solution but I can't quite figure out the coding for file.rename to do this, where most examples are for individual files, or files within the working directory.

This is my attempt from looking at examples on Stack Exchange, but this did not work:

original_path <- 'animals/photos'
renamed_list <- dir(path = original_path, pattern = '*.png')

sapply(X = renamed_list, FUN = function(x) {
  file.rename(paste0(original_path, x),
              paste0(original_path, 'Animal', substring(x, first = 1))) }) 

Thank you in advance

2

There are 2 answers

4
Rui Barradas On BEST ANSWER

Here is a function that does what you ask for.
The main problem is to assemble the new names from the old names' path and file extension. This is done with functions

  • basename and dirname in package base;
  • file_ext and file_path_sans_ext in package tools.

The consecutive numbers are produced by seq_along. Then paste0, sprintf and file.path put everything together.

If you want all numbers to have the same number of digits, change the format part of the fmt_string string to "%04d.%s".

file_rename_custom <- function(path, pattern, prefix = "Animals") {
  files_vec <- list.files(path = path, pattern = pattern, full.names = TRUE)
  ext <- tools::file_ext(files_vec)
  fname <- files_vec |>
    basename() |> 
    tools::file_path_sans_ext()
  
  fmt_string <- paste0(prefix, "%0", length(files_vec), "d.%s")
  new_name <- sprintf(fmt_string, seq_along(fname), ext)
  new_name <- file.path(dirname(files_vec), new_name)
  
  file.rename(files_vec, new_name)
}

working_directory <- getwd()
wd1 <- file.path(working_directory, "animals/photos")
wd2 <- file.path(working_directory, "animals")

dir(wd1)
# [1] "Cat.txt"    "Chiken.txt" "Moose.txt" 
file_rename_custom(wd1, "\\.txt")
# [1] TRUE TRUE TRUE
dir(wd1)
# [1] "Animals1.txt" "Animals2.txt" "Animals3.txt"

dir(wd2)
# [1] "Cat.txt"    "Chiken.txt" "Moose.txt"  "photos"    
file_rename_custom(wd2, "\\.txt")
# [1] TRUE TRUE TRUE
dir(wd2)
# [1] "Animals1.txt" "Animals2.txt" "Animals3.txt" "photos"
0
B. Christian Kamgang On

Another way to solve your problem:

file.rename(from = Sys.glob(file.path(original_path, "*.png")), 
            to = file.path(original_path, paste0("Animal", seq_along(files), ".png")))