28static const char *
const kShortHelp =
"usage: rootrm [-h] [-i|--interactive] [-r|--recursive] "
29 "[-v|--verbose] FILE[:path/to/obj] [...]\n";
31Remove objects from ROOT files
34 FILE:path File(s) and path of objects to remove
37 -f, --force ignore nonexistent files and arguments, never prompt
38 -h, --help show this help message and exit
39 -i, --interactive prompt before deleting each object
40 -n, --dry-run show what would be removed, but don't actually remove anything. Implies `-v`.
41 -r, --recursive recurse inside directories
42 -v, --verbose be verbose (can be repeated for increased verbosity)
45- rootrm example.root:hist
46 Remove the object 'hist' from the ROOT file 'example.root'
48- rootrm example.root:dir/hist
49 Remove the object 'hist' from the directory 'dir' inside the ROOT file 'example.root'
52 Remove the ROOT file 'example.root'
54- rootrm -i example.root:hist
55 Display a confirmation request before deleting: 'remove 'hist' from 'example.root' ? (y/n) :'
79 opts.
AddFlag({
"-f",
"--force"});
81 opts.
AddFlag({
"-i",
"--interactive"});
82 opts.
AddFlag({
"-n",
"--dry-run"});
83 opts.
AddFlag({
"-r",
"--recursive"});
86 opts.
Parse(args, nArgs);
89 std::cerr <<
err <<
"\n";
115 Err() <<
"-i and -f flags are mutually exclusive.\n";
125 std::cout <<
"remove '" << fileName <<
"' ? (y/n) ";
127 std::cout <<
"remove '" << objName <<
"' from '" << fileName <<
"' ? (y/n) ";
130 return answer ==
'y' || answer ==
'Y';
139 const bool nodeIsRootFile = !
node.fKey;
140 std::string_view objName = nodeIsRootFile ? std::string_view{} :
node.fName;
142 if (
node.fDir && !args.fRecursive) {
144 Err() <<
"cannot remove '" <<
node.fName <<
"': is a ROOT file. Use -r to remove it.\n";
146 Err() <<
"cannot remove '" <<
node.fName <<
"': is a directory. Use -r to remove it.\n";
155 if (nodeIsRootFile) {
159 if (res < 0 && !args.fForce) {
173 node.fKey->Delete(opt);
186 auto args =
ParseArgs(
const_cast<const char **
>(argv) + 1, argc - 1);
197 std::vector<std::pair<std::string_view, std::string_view>> sourcesFileAndPattern;
198 sourcesFileAndPattern.reserve(args.fSources.size());
199 for (
const auto &src : args.fSources) {
202 Err() << res.GetError()->GetReport() <<
"\n";
205 auto fNameAndPattern = res.Unwrap();
206 sourcesFileAndPattern.push_back(fNameAndPattern);
210 std::vector<std::string_view> filesDeleted;
212 for (
const auto &[srcFname, srcPattern] : sourcesFileAndPattern) {
214 if (std::find(filesDeleted.begin(), filesDeleted.end(), srcFname) != filesDeleted.end()) {
219 if (!src.fErrors.empty()) {
224 for (
const auto &
err : src.fErrors)
232 assert(!
gROOT->GetListOfFiles()->Contains(src.fObjectTree.fFile.get()));
235 for (
auto nodeIdx : src.fObjectTree.fLeafList) {
237 filesDeleted.push_back(srcFname);
241 for (
auto nodeIdx : src.fObjectTree.fDirList) {
243 filesDeleted.push_back(srcFname);
const char Option_t
Option string (const char).
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
std::vector< double > errors
void AddFlag(std::initializer_list< std::string_view > aliases, EFlagType type=EFlagType::kSwitch, std::string_view help="", std::uint32_t flagOpts=0)
Defines a new flag (either a switch or a flag with argument).
const std::vector< std::string > & GetErrors() const
Returns all parsing errors.
int GetSwitch(std::string_view name) const
If name refers to a previously-defined switch (i.e.
const std::vector< std::string > & GetArgs() const
Retrieves all positional arguments.
void Parse(const char **args, std::size_t nArgs)
@ kFlagAllowMultiple
Flag is allowed to appear multiple times (default: it's an error to see the same flag twice).
subroutine node(ivo, nuserm, iposp)
void SetLogVerbosity(int verbosity)
void InitLog(const char *name, int defaultVerbosity=1)
ROOT::RResult< std::pair< std::string_view, std::string_view > > SplitIntoFileNameAndPattern(std::string_view sourceRaw)
Given a string like "root://file.root:a/b/c", splits it into { "root://file.root",...
std::string NodeFullPath(const RootObjTree &tree, NodeIdx_t nodeIdx, ENodeFullPathOpt opt)
Given a node, returns its full path. If opt == kIncludeFilename, the path is prepended by "filename....
@ kRecursive
Recurse into subdirectories when matching objects.
RootSource GetMatchingPathsInFile(std::string_view fileName, std::string_view pattern, std::uint32_t flags)
Given a file and a "path pattern", returns a RootSource containing the tree of matched objects.
static const char *const kShortHelp
Command line tool to open a ROOT file on a TBrowser.
static const char *const kLongHelp
static bool RemoveNode(RootSource &src, NodeIdx_t nodeIdx, const RootRmArgs &args)
static bool PromptForRemoval(std::string_view fileName, std::string_view objName)
static RootRmArgs ParseArgs(const char **args, int nArgs)
std::unique_ptr< TFile > fFile
std::vector< RootObjNode > fNodes
std::vector< std::string > fSources