I often need to find a bunch of files in a particular folder, and if I also need to get files in subfolders also, it can be a little longwinded. I prefer to deal with an array of matching files rather than mess around with file iterators, and I also prefer to deal with folder paths (such as /books/going gas/assets) rather than with folder ids.

This utility is available from the cUseful library, and will generate an array of matching files, taking care of recursing into folder structures as well as allowing you to specify folder paths instead of folder ids if you prefer.

Using DriveUtils

Since the cUseful library is dependency free, you need to pass it your DriveApp and provoke a drive authorization the first time you run your script. If youa re calling any functions from the DriveUtils namespace of cUseful, your script should always start with this line (including the comment).

var driveUtils =   cUseful.DriveUtils.setService (DriveApp);   // DriveApp.getFiles()

By making cUseful dependency free like this, it can be included in scripts without generating unnecessary requests for authorization. If you are building a multipurpose library, this is a good approach to keep authorization requests relevant to users of your library.

How to use

Let’s say I want all files in the folder under a path on Drive that starts with “/Published slides”.

var files = driveUtils.getPileOfFiles ("/Published slides");

More likely though I’ll want a specific type of file – in this case presentations – so I’ll add the mimetype for presentations

var files = driveUtils.getPileOfFiles ("/Published slides",""application/vnd.google-apps.presentation");

If I want the files in all the subfolders too, I can do this

var files = driveUtils.getPileOfFiles ("/Published slides","application/vnd.google-apps.presentation", true);

The result

Here’s what the resultant pile of files looks like. The file and folder properties are DriveApp File and Folder objects respectively.

[{
  "file": {},
  "folder": {},
  "path": "/Published slides/gas5/do something in 5 with gas-8-copy between databases"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/gas5/do something in 5 with gas-9-copy between databases with oauth2"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/gas5/do something in 5 with gas-7-email log"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/gas5/do something in 5 with gas-1-use spreadsheet as database"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/gas5/do something in 5 with gas-6-fusionCrossfilter"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/gas5/do something in 5 with gas-5-anltycs"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/gas5/do something in 5 with gas-4-anltycs"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/gas5/do something in 5 with gas-3-simple invoicing app"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/gas5/do something in 5 with gas-2-graduate to a database"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/gdg/final Instrumentation with Analytics.pptx"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/gdg/Instrumentation with Analytics.pptx"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/sprint/bsprint deck"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/Goa tutorial"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/getting started with dbabstraction"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/Untitled presentation"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/dogger"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/scratchDB concept"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/gasdash"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/analytics to sites"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/getting started with cezyoauth2"
 }, {
  "file": {},
  "folder": {},
  "path": "/Published slides/dbabstraction"
  }]

Using the folder id

If you prefer to use the folder id rather than the path, just supply it instead of a path, as below.
var files = driveUtils.getPileOfFiles (“0B92ExLh4POiZR1pFTlBaREFfcWs”,”application/vnd.google-apps.presentation”, true);

The returned result will be the same regardless of whether you provided an id or a path.

The code

You’ll need the cUseful library (key below), or you can pull it from github to create your own copy.

Mcbr-v4SsYKJP7JMohttAZyz3TLx7pV4j

A quick visual test is this webapp, which I’ve used to enumerate my drive.


The code is below and on github.
function doGet() {
  return HtmlService.createTemplateFromFile('index')
  .evaluate()
  .setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function enumerateFiles(startPath,mime , recurse) {
  // DriveApp.getFiles()
  var start = new Date().getTime();
  var pile = cUseful.DriveUtils
  .setService(DriveApp)
  .getPileOfFiles (startPath,mime , recurse);
  
  return {
    results:pile.map (function(d) {
      return {
        folderId:d.folder.getId(),
        fileId:d.file.getId(),
        path:d.path
      };
    }),
    elapsed:new Date().getTime() - start
  };

}

index.html

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
    <base target="_top">
  </head>
  <body>
    <? var data = enumerateFiles('/' , '' , true ); 
       var headings = data.results.length ? Object.keys(data.results[0]) : []; 
    ?>
    <p>
      Elapsed ms <?=data.elapsed?>
      files <?=data.results.length?>
      ms per file <?=Math.round(data.elapsed/data.results.length)?>
    </p>
    <table>
    <tr>
      <? headings.forEach (function(h) {
        ?><th><?=h?></th>
      <? }); ?>  
    </tr>
      <? data.results.forEach(function(d) { ?><tr><?
         headings.forEach (function(h) {
          ?><td><?=d[h]?></td>
          <?});?>
         </tr> <?
         });
       ?>
    </table>
  </body>
</html>
For more like this see Google Apps Scripts Snippets
Why not join our forum, follow the blog or follow me on twitter to ensure you get updates when they are available.