Найти данные в папках и сообщить об отсутствующих данных

#r #directory #feedback

#r #каталог #Отзывы

Вопрос:

У меня есть R-скрипт для создания нескольких небольших частей большого набора данных (на самом деле это набор данных по Европе). Нам нужны эти небольшие части (плитки), чтобы редактировать эти плитки было проще, чем с одним большим набором данных.

Теперь у меня есть 1 папка Windows, и в этой папке у меня есть 966 автоматически сгенерированных папок — каждая с 4 наборами данных (я надеюсь, что по крайней мере это 4). Нам нужно знать, есть ли именно эти 4 набора данных в папках, и если какой-то набор данных отсутствует, нам нужно знать, какой именно. Код, который вы можете видеть ниже, создает папки. Он опубликован только для того, чтобы вы знали о структурах.

 in_file <- "P:/High_Resolution_Layers/Forest... .tif/2015/TCD_2015_020m_eu_03035_d04_full/TCD_2015_020m_eu_03035_d04_full.tif"


for (t in 1:length(tiles)){

  tileID <- tiles[t]

  out_dir <- file.path(output_dir,tileID)
  # out_dir_tmp <- file.path(out_dir, "tmp")
  if(!exists(out_dir)) {dir.create(out_dir, recursive = T)}
  # if(!exists(out_dir)) {dir.create(out_dir_tmp, recursive = T)}

  # tmp_file <- file.path(out_dir_tmp, paste0(tileID, "_HRL_Forest.tif")) ## <- ändern ("_HRL_Forest.tif", _clc_2012.tif, _clc_2018.tif, _slope.tif)
  out_file <- file.path(out_dir, paste0(tileID, "_HRL_Forest.tif")) ## <- ändern ("_HRL_Forest.tif", _clc_2012.tif, _clc_2018.tif, _slope.tif)

  cmd <- paste("gdalwarp",
               "-overwrite",
               "-s_srs EPSG:3035",
               "-t_srs EPSG:3035",
               "-r near",
               "-q",
               "-tr 20 20",
               "-te ", tile_list[t,3],tile_list[t,4],tile_list[t,3] 100000, tile_list[t,4] 100000,
               "-tap",
               "-of GTiff",
               in_file,
               out_file)

  system(osgeo, input=cmd)

  # cmd <- sprintf('gdal_translate -ot Byte -a_nodata 255 -co "COMPRESS=LZW" %s %s', tmp_file, out_file)
  # system(osgeo, input=cmd)

  # unlink(out_dir_tmp,recursive=T)
}
  

Комментарии:

1. Наличие кода здесь — это хорошо, но, признаюсь, у меня мало желания запускать что-то, что генерирует почти 1000 папок и файлов в каждой. Точно так же, вашей проблеме не нужно gdalwarp обращаться к источнику вашего вопроса. Можете ли вы адаптировать / уменьшить проблему, чтобы проверить наличие 3 папок с 2-4 текстовыми файлами в каждой? Хитрость в том, чтобы заставить больше людей взглянуть на него, заключается в том, чтобы сделать его легко воспроизводимым, и совпадение venn пользователей с gdalwarp установленным и пользователей на SO может быть небольшим. Кроме того, что вы пробовали для автоматизации проверки?

2. «Можете ли вы адаптировать / уменьшить проблему для проверки наличия 3 папок с 2-4 текстовыми файлами в каждой?» -> Нет, нам нужна именно такая структура. 926 папок с несколькими файлами (до 10 файлов). «что вы пробовали для автоматизации проверки?» -> Я пробовал это со следующими выражениями: list.files(path = «T:/Processing/2734_EEA_HRL2018_Lot1/02_Interim_Products/LOT1_input_tiles «, pattern = NULL, all.files = FALSE, full.names = FALSE, recursive = TRUE, ignore.case = FALSE, include.dirs = TRUE, no .. = FALSE) Но максимальные ограничения на запись ограничивают это, и я не знаю, отсутствует ли sth

3. Я думаю, что мой ответ соответствует моей точке зрения, но для ясности: я не спрашивал, можете ли вы изменить свои фактические требования, я предполагал, что вы могли бы упростить способ постановки вопроса, чтобы сделать его минимальным . И поскольку у нас нет никаких файлов для «воспроизведения» и тестирования, это также не рабочий пример. Вы можете увидеть, что люди запрашивают это как «MWE», также сформулированный как полностью воспроизводимый (но все же минимальный) вопрос.

Ответ №1:

Я собираюсь составить структуру и список файлов.

  • каталоги A через D
  • в каждом каталоге должны быть файлы a.tif , хотя c.tif

Поскольку во всех каталогах должны быть одинаковые файлы, мы можем выполнить их декартово / outer объединение:

 dirs <- LETTERS[1:4]
files_each_dir <- paste0(letters[1:3], ".tif")
(all_files <- outer(dirs, files_each_dir, file.path))
#      [,1]      [,2]      [,3]     
# [1,] "A/a.tif" "A/b.tif" "A/c.tif"
# [2,] "B/a.tif" "B/b.tif" "B/c.tif"
# [3,] "C/a.tif" "C/b.tif" "C/c.tif"
# [4,] "D/a.tif" "D/b.tif" "D/c.tif"
  

Поскольку нам не нужен matrix , я удалю их из списка, а затем создам каталоги / файлы:

 c(all_files)
#  [1] "A/a.tif" "B/a.tif" "C/a.tif" "D/a.tif" "A/b.tif" "B/b.tif" "C/b.tif"
#  [8] "D/b.tif" "A/c.tif" "B/c.tif" "C/c.tif" "D/c.tif"
for (d in dirs) dir.create(d)
for (p in all_files) writeLines(p, p)
  

Все ожидаемые файлы существуют

 (files_found <- list.files(pattern = "*.tif", recursive = TRUE, full.names = TRUE))
#  [1] "./A/a.tif" "./A/b.tif" "./A/c.tif" "./B/a.tif" "./B/b.tif" "./B/c.tif"
#  [7] "./C/a.tif" "./C/b.tif" "./C/c.tif" "./D/a.tif" "./D/b.tif" "./D/c.tif"
### remove the leading "./"
(files_found <- gsub("^\./", "", files_found))
#  [1] "A/a.tif" "A/b.tif" "A/c.tif" "B/a.tif" "B/b.tif" "B/c.tif" "C/a.tif"
#  [8] "C/b.tif" "C/c.tif" "D/a.tif" "D/b.tif" "D/c.tif"
all(all_files %in% files_found)
# [1] TRUE
all_files[!all_files %in% files_found]
# character(0)
  

Протестируйте отсутствующий файл:

 file.remove("B/c.tif")
# [1] TRUE
files_found <- list.files(pattern = "*.tif", recursive = TRUE, full.names = TRUE)
files_found <- gsub("^\./", "", files_found)
all_files[!all_files %in% files_found]
# [1] "B/c.tif"
  

Примечание: мы не используем files_each_dir ни для одного из последующих тестов. Это необходимо только в том случае, если мы ожидаем фиксированный набор имен файлов.

Подсчитайте файлы в каждом каталоге

Если имена файлов могут отличаться, то мы можем подсчитать количество файлов в каждом каталоге, независимо от фактических имен.

 (len3 <- lengths(split(files_found, sapply(strsplit(files_found, "[/\]"), `[[`, 1))) == 3)
#     A     B     C     D 
#  TRUE FALSE  TRUE  TRUE 
names(len3)[ !len3 ]
# [1] "B"
  

Содержимое файла

Если вам нужно проверить содержимое так, чтобы какое-то условие было истинным, попробуйте что-то вроде этого. Здесь я использую простую команду оболочки grep , но любая функция (R или shell), которая принимает путь и возвращает что-то, что вам нужно (размер, свойство и т.д.), Должна работать.

 func <- function(path) length(system2("grep", c("-lE", "'[a-z]'", path), stdout = TRUE)) > 0
(proper_contents <- sapply(files_found, func))
# A/a.tif A/b.tif A/c.tif B/a.tif B/b.tif C/a.tif C/b.tif C/c.tif D/a.tif D/b.tif 
#    TRUE    TRUE    TRUE    TRUE    TRUE    TRUE    TRUE    TRUE    TRUE    TRUE 
# D/c.tif 
#    TRUE 
  

Давайте изменим содержимое одного файла на test:

 writeLines("123", "D/a.tif")
proper_contents <- sapply(files_found, func)
# Warning in system2("grep", c("-lE", "'[a-z]'", path), stdout = TRUE) :
#   running command '"grep" -lE '[a-z]' D/a.tif' had status 1
names(proper_contents)[ !proper_contents ]
# [1] "D/a.tif"