I've a list of hundreds of rasters that I've renamed, but when I export using writeRaster, the filenames have not changed.

For example:

# all the of the packages I have loaded during actual work session... 
# if (!require("pacman")) install.packages("pacman"); library(pacman)
# p_load(here, tidyverse, sf,lubridate, raster, terra, janitor)

# read  list of files
(file_list <- list.files(here("test_set"), 
                         pattern="tif$", full.names = TRUE, recursive=FALSE))
# get names from list 
(file_names <- tools::file_path_sans_ext(list.files(here("test_set"), 
                                                    pattern="tif$", full.names = FALSE)) %>% 
    # remove everything after 1st underscore 
# read list of rasters
(r <- map(file_list, rast))

# rename the list 
(names(r) <- file_names)

map(r, function (i) 
  writeRaster(i, filename=paste0(here("test_set/new_names//"), names(i),".tif"), overwrite=TRUE))

I'd like to write the rasters to disk using the shortened names.

2 Answers 2


You are really over complicating this endeavor. This can easily be done with an iterator (for, lapply, ...) by simply operating on the vector of raster names.

in.dir <- "C:/inrast"
out.dir <- "C:/outrast"

file_list <- list.files(in.dir, "tif$", full.names = TRUE)

lapply(file_list, function(i) { 
 writeRaster(rast(i), file.path(out.dir, 
   paste0(str_extract(basename(i), "[^_]+"), ".tif")))

So, in unpacking this code, lapply is acting as an iterator on the file_list vector of raster names. We are reading the raster on-the-fly using terra::rast within terra::writeRaster. The raster is being written to the out.dir (just to keep results separate). I am using the same syntax for stringr::str_extract and basename just extracts the end of the path name.

Here is a break down the nested function calls used in naming the new raster;

( x <- "C:/indir/file01_to_rename.tif" )
    # "C:/indir/file01_to_rename.tif"
( x <- basename(x) )
    # "file01_to_rename.tif"
( x <- str_extract(x, "[^_]+") ) 
    # "file01"
file.path("C:/outrast", paste0(x, ".tif"))
    # "C:/outrast/file01.tif"

Now put together, if the paths and names are included

    "[^_]+"), ".tif"))
      # "C:/outrast/file01.tif"

Why would you use writeRaster if your (apparent) goal it to just copy the files to a new path/name?

# get the input files (*not* a list!)
fin  <- list.files("test_set", pattern="tif$", full.names=TRUE))

# we do not have your files, so I use example names instead
fin <- c("test_set/rat1_1.tif", "test_set/rat2_2.tif", "test_set/rat3_3.tif")

# remove everything after first underscore
fout <- sapply(basename(fin), \(i) strsplit(i, "_")[[1]][1], USE.NAMES=FALSE)
# make output files
fout <- paste0("test_set/new_names/", fout, ".tif")
#[1] "test_set/new_names/rat1.tif" "test_set/new_names/rat2.tif"
#[3] "test_set/new_names/rat3.tif"

# copy the files
file.copy(fin, fout)

But if you were changing the format or compression or something like that, you could do something like this

for (i in seq_along(fin)) {
   rast(fin[i]) |> writeRaster(fout[i])
  • Ah, so true. You can simply use file management functions. Forest through the trees and all that. Commented Feb 2, 2023 at 5:16
  • That was just a quick example. I crop (and mask) and reclassify the rasters and then export.
    – derelict
    Commented Feb 2, 2023 at 13:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.