3

I have a Google Drive structure setup like this:

Client A
--Project 1
----Drafts
----Presentations
----Minutes
--Project 2
----Drafts
----Presentations
----Minutes
Client B
<and so on>

I want to write a script where I can pass in the ID of Project 1, and it will loop through each of the three subfolders and count the total number of files (ultimately I want to count the number of files updated over a date range, but baby steps!).

I've tried using the Class FolderIterator code, but that wants you to assign a group of folders to a variable "folders" (it showed var folders = DriveApp.getFolders(); and I tried var folders = DriveApp.getFolderById("<id of Project 1 here>"); but in my version that's just one folder, and it really needs the collection of folders). Is there a way to assign those three subfolders to that folders variable if I have the ID of the parent folder? Or is there a better way to loop through the subfolders?

rryanp
  • 1,027
  • 8
  • 26
  • 45

2 Answers2

2

As a complement to Bryan's answer (thx, I upvoted) I wrote a test function to see results in the logger and to run the function with appropriate parameters to get the count you wanted.

(This answer should not be selected as the right answer since the main part is from Bryan P)

here is how it goes :

    function testTraverse(){
      var originFolder = DriveApp.getFoldersByName('Client A').next(); // use the folder name you want here
      var totalCount = traverseFolder(originFolder,0);
      Logger.log('total files = '+totalCount);// note that if some files are
      // in more than one subfolder the count will count every occurrence of 
      //this file so the total might be > to the sum of intermediate values
    }

    function traverseFolder(folder,total) {
      var name = folder.getName();
      var count = 0;
      var files = folder.getFiles();

      while (files.hasNext()) {
        count++; 
      Logger.log('fileName ('+count+') in '+name+' is : '+files.next().getName());

      }
      Logger.log('\n'+name+' has ' + count+' files\n----------------------\n' );
      var subs = folder.getFolders();
      while (subs.hasNext()) {
        total+=traverseFolder(subs.next(),count);
      }
      return total;
    }

Note that this code will work for a "reasonable" number of files, if you have many files and folders it might exceed the 5 minutes execution time limit. In this case you'll need to modify it in order to proceed by smaller bunches of files using the token provided by the method.

Serge insas
  • 45,904
  • 7
  • 105
  • 131
  • Many thanks to both of you--this is truly incredible...I haven't fully figured it all out yet, but it works like a charm, and I look forward to digging into it and understanding it all. I appreciate it. I gave the correct answer to Bryan based on Serge's note but wish I could have given it to both of you. – rryanp Aug 06 '14 at 01:13
  • This has worked great, though now I'm trying to write all the files to a Google Spreadsheet, and I'm struggling with the counter to keep track of the current spreadsheet row (since the function calls itself, any counter I track gets reset or modified)...is there a way to use/maintain a global counter variable? Something I could set outside of the function that keeps its value over time? As a workaround now, I just use the log file, and that works great--just want something a little more user friendly. Thanks! – rryanp Aug 20 '14 at 14:23
  • I'm not sure I understand... var total is already a global counter... what else exactly do you need ? – Serge insas Aug 20 '14 at 14:33
  • For some reason total remains 0 for me throughout the entire process (I've tried logging it at each iteration and at the end). I'll go review my code again--maybe I missed something. Thanks! – rryanp Aug 20 '14 at 20:09
1

It may look some thing like this with DriveApp...

function traverseFolder(folder) {
  var name = folder.getName();

  if ( /^(Drafts|Presentations|Minutes)$/.test(name) ) { 
    var count = 0;
    var files = folder.getFiles();

    while ( files.hasNext() ) {
      count++; 
    }
    Logger.log(name + ' : ' + count);
  }
  var subs = folder.getFolders();

  while (subs.hasNext()) {
    traverseFolder(subs.next());
  }
}

We now have access to the Advanced Drive Service too. Maybe I'll look at an example with that if some one doesn't post one soon.

Bryan P
  • 5,031
  • 3
  • 30
  • 44
  • You made a small mistake : `if ( files.hasNext() ) { count++; ` is not an `IF` condition but a `while` loop. I'm sure it is a typo when you wrote the code. Though I upvoted for the idea ;-) – Serge insas Aug 05 '14 at 22:39
  • Thanks. Think I was trying for a `.length` or `.size()` method to begin with instead of looping. Nothing like that to use in this case, right? – Bryan P Aug 05 '14 at 23:02
  • Yes indeed, while is the appropriate tool :-) DocsList returns arrays and thus allows us to loop in a for/next loop using array.length but not DriveApp. – Serge insas Aug 05 '14 at 23:29
  • Thanks a lot, Bryan--this is great and I appreciate you taking the time! The code works really well and does exactly what I need. – rryanp Aug 06 '14 at 01:13