如何监测Data子目录变化并自动运行R脚本生成Rmd报告?
解决方案:基于目录状态校验的自动化报告生成流程
一、核心思路
用目录状态指纹(子目录的文件列表、总大小、最后修改时间的哈希值)判断是否有变化,避免重复生成报告。每次运行脚本时,对比当前状态和上次记录的状态,仅在状态不一致时执行报告生成。
二、具体实现步骤
1. 记录目录状态
创建dir_status.rds状态文件,存储每个运动项目子目录的关键状态信息:
library(dplyr) library(digest) # 定义路径 data_root <- "./Data" status_file <- "./dir_status.rds" # 获取当前子目录状态 get_current_status <- function() { sport_dirs <- list.dirs(data_root, recursive = FALSE, full.names = TRUE) dir_status <- lapply(sport_dirs, function(dir) { csv_files <- list.files(dir, pattern = "\\.csv$", full.names = TRUE) if(length(csv_files) == 0) return(NULL) total_size <- sum(file.size(csv_files)) latest_mtime <- max(file.mtime(csv_files)) fingerprint <- digest(list(dir, total_size, latest_mtime), algo = "md5") data.frame( sport_dir = basename(dir), full_path = dir, total_size = total_size, latest_mtime = as.character(latest_mtime), fingerprint = fingerprint, stringsAsFactors = FALSE ) }) %>% bind_rows() return(dir_status) } # 首次运行初始化状态文件 if(!file.exists(status_file)) { initial_status <- get_current_status() saveRDS(initial_status, status_file) }
2. 对比状态并触发报告生成
读取历史状态,找出变化的子目录,针对性生成报告:
# 读取历史与当前状态 prev_status <- readRDS(status_file) current_status <- get_current_status() # 筛选状态变化或新增的目录 changed_dirs <- anti_join(current_status, prev_status, by = "sport_dir") %>% bind_rows(filter(current_status, !fingerprint %in% prev_status$fingerprint)) # 为变化目录生成报告 if(nrow(changed_dirs) > 0) { library(rmarkdown) for(i in 1:nrow(changed_dirs)) { dir_path <- changed_dirs$full_path[i] sport_name <- changed_dirs$sport_dir[i] report_path <- file.path("./reports", paste0(sport_name, "_report.html")) # 调用Rmd模板生成报告(模板需支持sport_dir参数) render( input = "./your_report_template.Rmd", output_file = report_path, params = list(sport_dir = dir_path) ) } # 更新状态文件 saveRDS(current_status, status_file) }
3. 每日调度设置
- Windows环境:用
taskscheduleR创建定时任务:
library(taskscheduleR) taskscheduler_create( taskname = "SportReportGenerator", rscript = "./auto_report_generator.R", schedule = "DAILY", starttime = "08:00", startdate = Sys.Date() )
- Linux/macOS环境:用
cronR配置cron任务:
library(cronR) cron_add( command = "Rscript /path/to/auto_report_generator.R", frequency = "daily", at = "08:00", id = "sport_report_generator" )
三、实时监听替代方案
如果需要实时响应目录变化(而非每日调度),用fs包的文件监听功能(需脚本持续后台运行):
library(fs) library(rmarkdown) data_root <- "./Data" status_file <- "./dir_status.rds" # 初始化状态文件(首次运行) if(!file.exists(status_file)) { saveRDS(get_current_status(), status_file) } watch_dir <- function() { while(TRUE) { # 监听目录变化,超时1小时 changes <- dir_watch(data_root, recursive = TRUE, timeout = 3600) if(length(changes) > 0) { # 提取变化对应的运动子目录 changed_sport_dirs <- unique(dirname(changes$path)) %>% grep(paste0("^", data_root, "/"), ., value = TRUE) %>% basename() %>% unique() # 生成对应报告 for(sport in changed_sport_dirs) { dir_path <- file.path(data_root, sport) report_path <- file.path("./reports", paste0(sport, "_report.html")) render( input = "./your_report_template.Rmd", output_file = report_path, params = list(sport_dir = dir_path) ) } # 更新状态文件 saveRDS(get_current_status(), status_file) Sys.sleep(60) # 避免短时间内重复触发 } } } watch_dir()
内容的提问来源于stack exchange,提问作者zmcclean
相关产品推荐
相关产品推荐

