How many Trees are in a root file?

Is there a function to get the number of Trees in a root file?


you can loop on the keys holding objects stored in a ROOT files and get their type name, e.g. “TTree” as follows:

for (auto&& keyAsObj : file->GetListOfKeys()){
 auto key = (TKey*) keyAsObj;
 cout << key->GetName() << " " << key->GetClassName() << endl;

if it is enough for you, you can achieve this with a command line utility, rootls

rootls myfile.root


Not sure this solution is addressing trees hidden in deep directories’ hierarchies. Is it?

Welcome to the Newbie category!
Here we take it easy and assume the case is the simplest possible :slight_smile:
With recursion this would look like

void listRecursive(TDirectoryFile *f, unsigned int nindent = 0) {
   const std::string indent(nindent, ' ');
   for (auto &&keyAsObj : *f->GetListOfKeys())
      auto key = (TKey *)keyAsObj;
      cout << indent << key->GetName() << " " << key->GetClassName() << endl;
      if (auto d = dynamic_cast<TDirectoryFile*>(key->ReadObj())) {
         listRecursive(d, nindent + 2);

void myMacro()

   TFile file("a.root");

but let’s not dive into solutions of problems if we do not know they exist!


People sometimes use TFolder based structures, which your scan does not cover (so, some trees may be missing in the list).

Also, if you scan TKey instances, you will get all “cycles” listed separately (so, some trees may appear many times in the list).

also, rootls from ROOT doesn’t handle subdirs nor recursion:

$> root --version -b -q
  | Welcome to ROOT 6.14/04       |
  |                               (c) 1995-2018, The ROOT Team |
  | Built for linuxx8664gcc                                    |
  | From tags/v6-14-04@v6-14-04, Aug 23 2018, 17:00:44         |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q' |

$> rootls -t -l ./dirs-6.14.00.root
TDirectoryFile  Jul 03 11:08 2018 dir1  "dir1"
TDirectoryFile  Jul 03 11:08 2018 dir2  "dir2"
TDirectoryFile  Jul 03 11:08 2018 dir3  "dir3"

groot/cmd/root-ls does :slight_smile:

$> root-ls -t ./dirs-6.14.00.root
=== [./dirs-6.14.00.root] ===
version: 61400
TDirectoryFile   dir1    dir1    (cycle=1)
  TDirectoryFile dir11   dir11   (cycle=1)
    TH1F         h1      h1      (cycle=1)
TDirectoryFile dir2    dir2    (cycle=1)
TDirectoryFile dir3    dir3    (cycle=1)

It is not fully true. Try:

rootls  "dirs-6.14.00.root:*" 

I stand corrected :slight_smile:

but it’s not super useful either:

$> rootls -l "dirs-6.14.00.root:*" 
dir1 :
  TDirectoryFile  Jul 03 11:08 2018 dir11  "dir11"
dir2 :
dir3 :

$> rootls -l "dirs-6.14.00.root:*/*" 
TH1F  Jul 03 11:08 2018 h1  "h1"