Search code examples
rmetadata

How to copy files with a particular metadata tag into a new folder using R?


I have a bunch of subfolders with images in them and some of the images have the tag "detection" in their metadata. I want to pick these files out and copy them to a new folder. This was as far as I got in trying to create a loop to do this:

metadata <- read_exif(file)
      
      #Check if the tag is in the metadata tags field
      if ("Tags" %in% names(metadata) && "detection" %in% metadata$Tags) {
        files_to_copy <- c(files_to_copy, file)
      }

where files_to_copy will be an empty vector to fill. Thanks in advance.


Solution

  • tibble from exifr:read_exif() includes full file paths in SourceFile column. Instead of looping though individual files, you can use a vector of all your file names (e.g. from list.files()) with read_exif(), filter / subset resulting frame and pass remaining SourceFile items to file.copy().

    Using example files from exifr package to copy files with FacesDetected tag:

    library(dplyr, warn.conflicts = FALSE)
    library(exifr)
    #> Using ExifTool version 12.22
    
    img_path <- system.file("images", package = "exifr")
    fs::dir_tree(img_path)
    #> D:/pkg_cache/renv/cache/v5/windows/R-4.4/x86_64-w64-mingw32/exifr/0.3.2/7e5e6d9140e2dbb379c1af6e24bc60da/exifr/images
    #> ├── binary_tag.JPG
    #> └── Canon.jpg
    
    dest_path <- tempfile("dir")
    dir.create(dest_path)
    
    list.files(img_path, full.names = TRUE) |> 
      read_exif(tags = "FacesDetected") |>
      # just for printing
      mutate(SourceFile = tibble::char(SourceFile, min_chars = 10, shorten = "front")) |> 
      print() |> 
      filter(!is.na(FacesDetected)) |> 
      pull(SourceFile) |> 
      file.copy(dest_path) 
    #> # A tibble: 2 × 2
    #>   SourceFile                         FacesDetected
    #>   <char>                                     <int>
    #> 1 …c60da/exifr/images/binary_tag.JPG             0
    #> 2 …6e24bc60da/exifr/images/Canon.jpg            NA
    #> [1] TRUE
    
    # files in destination dir:
    fs::dir_tree(dest_path)
    #> Temp\RtmpKuHss4\dir7050a398c0
    #> └── binary_tag.JPG