Search code examples
rmovesubdirectorymovefile

Moving files to subdirectory in R based on file name


So I would like to copy files to a specific folder based on a certain part in their name. For your overview I put my folder structure below. In the folders D0 and D1 I have multiple files (as example I put names of two files here) and the folders Weather and Temperature. I would like to move the .txt files to either the folder Weather or Temperature depending on whether the file name has Weather in its name or Temperature (see what I would like).

Current situation:

main Directory
|
|___ Experiment
        ├── D0
           ├── temperature
        │  └── Weather
           |__ Weather 100.txt
           |__ Temperature 100.txt
        └── D1
           ├── temperature
           └── weather
           |__ Weather 100.txt
           |__ Temperature 100.txt

What I would like:

main Directory
    |
    |___ Experiment
            ├── D1
               ├── Weather
                        |__Weather 100.txt
               └── Temperature
                        |__ Temperature 100.txt

I tried to do it in steps, so first the D0 to move the Weather, and then go further with D0 and move the Temperature files, D1 Weather and lastly the D1 Temperature files.

The problem however is twofold. The first obstacle is that although I get a list of files with Weather, once I want to copy it to a new directory I get an error saying that it cannot copy the file because there is no such file or directory. What is wrong with my code? The second problem is that the code is not so efficient if I want to do it like this, because I have to run the code four times (and even more if there are more than two maps (D3, D4 etc.). Is there a way to make the code more efficient, so it can do it all at once?


Solution

  • Here is a function that first gets the directories in ./Experiment and then applies a function fun to each of them, moving the files it finds to sub-directories sharing part of the name.

    fun <- function(path){
      files <- list.files(path = path)
      files <- file.path(path, files)
      info <- file.info(files)
      dirs <- files[info$isdir]
      fls <- files[!info$isdir]
      out <- lapply(dirs, function(d){
        i <- grep(basename(d), fls, ignore.case = TRUE)
        if(length(i)){
          to <- file.path(d, basename(fls[i]))
          tryCatch(
            file.rename(fls[i], to = to),
            error = function(e) e
          )
        } else NULL
      })
      out
    }
    
    setwd('~/tmp/Experiment')
    d <- list.dirs(recursive = FALSE)
    sapply(d, fun)