ROOT 6.24.06环境下如何逐个合并2800个.root文件以降低内存占用?
逐次合并ROOT文件以降低内存占用方案
针对ROOT 6.24.06版本,以下两种方案可实现逐个加载合并文件,大幅降低内存消耗:
一、Shell循环逐次合并
利用hadd命令每次仅合并当前输出文件与单个源文件,避免一次性加载所有文件。
基础版(文件名无空格)
SOURCE_DIRECTORY="/input_directory/" OUTPUT_FILE="/output_directory/output.root" # 复制第一个文件作为初始输出 first_file=$(ls "$SOURCE_DIRECTORY"/*.root | head -n 1) cp "$first_file" "$OUTPUT_FILE" # 循环合并剩余文件 for file in $(ls "$SOURCE_DIRECTORY"/*.root | tail -n +2); do hadd -f -k "$OUTPUT_FILE" "$OUTPUT_FILE" "$file" done
鲁棒版(支持带空格的文件名)
SOURCE_DIRECTORY="/input_directory/" OUTPUT_FILE="/output_directory/output.root" # 获取第一个文件 first_file=$(find "$SOURCE_DIRECTORY" -maxdepth 1 -type f -name "*.root" | head -n 1) cp "$first_file" "$OUTPUT_FILE" # 循环处理剩余文件 find "$SOURCE_DIRECTORY" -maxdepth 1 -type f -name "*.root" | tail -n +2 | while read -r file; do hadd -f -k "$OUTPUT_FILE" "$OUTPUT_FILE" "$file" done
参数说明:
-f: 强制覆盖已存在的输出文件-k: 保留损坏文件(可选,根据实际需求添加)
二、ROOT宏脚本(C++)
通过ROOT的C++宏实现更灵活的逐次合并,适合需自定义逻辑的场景。
编写宏文件merge_files.C
#include <TFile.h> #include <TChain.h> #include <TSystem.h> #include <vector> #include <string> #include <cstdio> void merge_files(const char* input_dir, const char* output_file) { // 遍历目录获取所有ROOT文件 std::vector<std::string> file_list; void* dir_handle = gSystem->OpenDirectory(input_dir); const char* entry; while ((entry = gSystem->GetDirEntry(dir_handle))) { std::string filename = entry; if (filename.find(".root") != std::string::npos && filename != "." && filename != "..") { file_list.push_back(std::string(input_dir) + "/" + filename); } } gSystem->FreeDirectory(dir_handle); if (file_list.empty()) { printf("Error: No ROOT files found in target directory.\n"); return; } // 初始化输出文件(复制第一个文件的结构) TFile* out_file = TFile::Open(output_file, "RECREATE"); TFile* first_in_file = TFile::Open(file_list[0].c_str()); first_in_file->Copy(*out_file); delete first_in_file; out_file->Close(); // 逐个合并剩余文件 for (size_t i = 1; i < file_list.size(); ++i) { printf("Merging %zu/%zu: %s\n", i+1, file_list.size(), file_list[i].c_str()); // 若已知树名,替换为TChain chain("your_tree_name")以提升效率 TChain chain(""); chain.Add(file_list[i].c_str()); chain.Merge(output_file, "UPDATE"); } printf("Merge finished successfully.\n"); }
运行宏
root -l -b -q 'merge_files.C("/input_directory/", "/output_directory/output.root")'
参数说明:
-l: 不显示ROOT启动界面-b: 批处理模式运行-q: 运行后退出ROOT
内容的提问来源于stack exchange,提问作者Krishna Neupane
相关产品推荐
相关产品推荐

