78

I have over 700 files in one folder named as: files from number 1 to number9 are named for the first month:

water_200101_01.img  
water_200101_09.img  

files from number 10 to number30 are named:

water_200101_10.img
water_200101_30.img

And so on for the second month: files from number 1 to number9 are named:

water_200102_01.img  
water_200102_09.img  

files from number 10 to number30 are named:

water_200102_10.img
water_200102_30.img 

How can I rename them without making any changes to the files. just change the nams, for example

water_1
water_2
...till...
water_700
zx8754
  • 52,746
  • 12
  • 114
  • 209
sacvf
  • 2,463
  • 5
  • 36
  • 54

4 Answers4

110

file.rename will rename files, and it can take a vector of both from and to names.

So something like:

file.rename(list.files(pattern="water_*.img"), paste0("water_", 1:700))

might work.

If care about the order specifically, you could either sort the list of files that currently exist, or if they follow a particular pattern, just create the vector of filenames directly (although I note that 700 is not a multiple of 30).

I will set aside the question, "why would you want to?" since you seem to be throwing away information in the filename, but presumably that information is contained elsewhere as well.

Brian Diggs
  • 57,757
  • 13
  • 166
  • 188
  • 4
    It's hard to read the error in the comments. It looks like `dir2` holds the names of the files to be renamed, so that should be the first argument to `file.rename` (instead of another `list.files` call). And you are missing a closing parenthesis at the end of the `list.files` call inside `file.rename` anyway. – Brian Diggs May 25 '12 at 18:20
  • Hi @Brian, when I do the similar thing, I get the `FALSE` message. The files fail to be renamed. The target folder named by `tmp_rename` contains three random files. And Here is my code `list.files('tmp_rename') %>% file.rename(to = c('a','b','c'))` – Jiaxiang Aug 13 '18 at 05:50
  • loved your solution, sadly, your solution does not seem to apply to UTF8 encoded file names such as : "קובץ מספר 1.xls" "קובץ מספר 2.xls" "קובץ מספר 3.xls" – amann Dec 16 '19 at 15:17
8

I wrote this for myself. It is fast, allows regex in find and replace, can ignore the file suffix, and can show what would happen in a "trial run" as well as protect against over-writing existing files.

If you are are on a mac, it can use applescript to pick out the current folder in the Finder as a target folder.

umx_rename_file <- function(findStr = "Finder", replaceStr = NA, baseFolder = "Finder", test = TRUE, ignoreSuffix = TRUE, listPattern = NULL, overwrite = FALSE) {
    umx_check(!is.na(replaceStr), "stop", "Please set a replaceStr to the replacement string you desire.")

    # ==============================
    # = 1. Set folder to search in =
    # ==============================
    if(baseFolder == "Finder"){
        baseFolder = system(intern = TRUE, "osascript -e 'tell application \"Finder\" to get the POSIX path of (target of front window as alias)'")
        message("Using front-most Finder window:", baseFolder)
    } else if(baseFolder == "") {
        baseFolder = paste(dirname(file.choose(new = FALSE)), "/", sep = "") ## choose a directory
        message("Using selected folder:", baseFolder)
    }

    # =================================================
    # = 2. Find files matching listPattern or findStr =
    # =================================================
    a = list.files(baseFolder, pattern = listPattern)
    message("found ", length(a), " possible files")

    changed = 0
    for (fn in a) {
        if(grepl(pattern = findStr, fn, perl= TRUE)){
            if(ignoreSuffix){
                # pull suffix and baseName (without suffix)
                baseName = sub(pattern = "(.*)(\\..*)$", x = fn, replacement = "\\1")
                suffix   = sub(pattern = "(.*)(\\..*)$", x = fn, replacement = "\\2")
                fnew = gsub(findStr, replacement = replaceStr, x = baseName, perl= TRUE) # replace all instances
                fnew = paste0(fnew, suffix)
            } else {
                fnew = gsub(findStr, replacement = replaceStr, x = fn, perl= TRUE) # replace all instances
            }
            if(test){
                message(fn, " would be changed to:  ", omxQuotes(fnew))
            } else {
                if((!overwrite) & file.exists(paste(baseFolder, fnew, sep = ""))){
                    message("renaming ", fn, "to", fnew, "failed as already exists. To overwrite set T")
                } else {
                    file.rename(paste0(baseFolder, fn), paste0(baseFolder, fnew))
                    changed = changed + 1;
                }
            }
        }else{
            if(test){
                # message(paste("bad file",fn))
            }
        }
    }
    if(test & changed==0){
        message("set test = FALSE to actually change files.")
    } else {
        umx_msg(changed)
    }
}
tim
  • 3,559
  • 1
  • 33
  • 46
8

If you want to replace a certain section of the file name that matches a given pattern with another pattern. This is useful for renaming several files at once. For example, this code would take all of your files containing foo and replace foo with bob in the file names.

file.rename(list.files(pattern = "foo"), str_replace(list.files(pattern = "foo"),pattern = "foo", "bob"))
Jamie Tock
  • 127
  • 1
  • 4
3

The following was my workaround for matching in sequence and changing all the filenames in a specified directory using simple base code.

old_files <- list.files(path = ".", pattern="water_*.img$")

# Create df for new files
new_files <- data.frame()

for(i in 1:length(old_files)){
new_files <- append(paste0(path = ".", substr(old_files[i], 1,6),"water_",i,".img"), new_files)
}

new_files <- as.character(new_files)

# Copy from old files to new files

file.rename(from = old_files), to = as.vector(new_files)