List all files and folders in a selected folder’s directory tree in Google Drive: Apps Script

List all files and Folders in a Directory Tree in Google Drive with Apps Script

If you have ever tried to get a list of all the child files and folders of a parent folder in Google Drive, you’ve no doubt discovered that it is a slow old process. Iterating over each item in a folder and then reading the metadata of that file or folder before calling the next one can take forever!

The built-in DriveApp Class for Google Apps Script is great for working on a small number of files and folders but it just doesn’t have the functionality to retrieve specific fields in your metadata, nor does the searchFiles method or searchFolders method have the ability to isolate just the fields that you want to retrieve. Subsequently, your processing time increases significantly as it ships junk data.

This tutorial is my attempt at, as the kiddies say today, creating a ‘blazingly fast’  file and folder iterator with Google’s Drive API v2 for Apps Script.

Skill level: Intermediate

Goat Club Rewards

What We’re Building

Our goal for this tutorial is to extract all of the child files and folders in the directory tree of a parent folder.

Directory tree of parent folder in Google Drive

To save some confusion later on we will call both files and folders, items. This is the same vernacular that the Google Drive API uses.

Once we have a list of all the items, we want to store them in a Google Sheet.

Our Google Sheet will contain the following columns:

  1. Icon (File or folder emoji for a quick visual reference)
  2. File Name
  3. File ID
  4. Parent Name (Parent folder, that is)
  5. Parent ID (We’ll throw in a link to the folder here too)
  6. File MIME type

So your Google Sheet will look a little like this:Sample Google Sheet of a list of all items from a directory tree in Google Drive with Apps Script Now, we are going to sacrifice some code simplicity in exchange for speed in this tutorial and I recommend that you follow along to get a full understanding of the code and how it works.

Strap in and let’s get started.

The Product Version

Not time to build this out yourself? I get it, life is hectic.

Grab a copy of the tutorial as a Product here.

To the Product!

Hire me for our next Google Workspace project.

The Starter Sheet

Grab your own copy of the starter sheet below. Then head to Extensions > Apps Script to get started.

List all items from a directory tree with Apps Script | STARTER

In the Google Apps Script IDE you will see two files, and Our main functions will be added to the file.

Note, that the “Drive API v2” Advanced Service has been added to the project. You can now call ‘Drive’ to access it.

Next, select a parent folder (Target folder) that you want to work with.

You can grab the id from the URL.[your folder id]

The Video Tutorial

Getting All the Google Drive Files and Folders in a Parent Folder with Apps Script

My first inclination here was to get a list of all items in the parent folder and then iterate over them calling the Drive API to retrieve each one. However, I knew that was frustratingly slow.

Instead, I thought I would use the Drive.Files.list() method. On its own, this will collect your entire list of files and folders in ‘My Drive’.

?You can support me for free by using this Amazon affiliate link in your next tech purchase :Computers & Stuff! ?

Not so surprisingly though, the process is pretty quick for the amount of data it is shipping. Why? Because it is making the query server-side in one big hit and then returns everything back.

Cool. I was on the right track, but I didn’t want all of my files and folders. I only wanted to collect the items starting from a selected parent folder.

Query the Drive API files list

Fortunately, one of the optional parameters of the ‘list’ method is ‘query’ represented as (q).

Great! So how do I make a query? Well, there was no link from the query definition to any documentation on this. C’mon, Google!

Scrolling down the sidebar in the docs did eventually reveal a list of Search Query Terms. The ‘parents’ query looked promising.

After a bit more stumbling around I came across a guide in the docs called ‘Search for files & folders’. Here there was a more concrete example of how to use the query.

"q" = "'[folder ID]' in parents"

Replace [folder ID] with your folder ID, but make sure you keep it in single quotation marks.

I also discovered a while ago that it is a good idea to add 'trashed = false' to ensure that any recently trashed files are not included in our list.

Stay classy my friends. 

Cool. I think we have enough now to run our first test.

Add the following to your file.

Update the folder ID in test_getFolderItems() and run the function.

Your results  should look a little like this:

It’s unlikely that you will be able to see everything in the returned object from the log. If you do want to see it all, you could store it in a JSON file like this:

Here you can see that the returned response contains a bunch of information about the request followed by an array with the property id, ‘items’. This will be where all of the files and folder data are stored.

Another noteworthy property is the "nextPageToken". This may not appear for you in your selected folder it only appears when the request reaches the maximum number of results it can return. By default, this is 100 results, but you can modify this to display fewer with 'maxResults' = [integer] parameter.

This will become useful for us later.

Looking at the item object metadata

Items are stored in an array of objects containing all the metadata for that object. Let’s take a look at an example. I’ll highlight all the parts that we will need to extract for our Google Sheet.

Here, you can see that we want to grab the following:

  1. "mimeType": "application/"
  2. "id": "1UjRKjrmti0mT7_rdBusrXJ0RIGeVBGOm" – inside 'parents'
  3. "title": "Basic Sheet and Notes Pages Template w/script"
  4. "id": "k2hlho34IamAgoat99two"

Get only selected fields from the Google Drive item with Google Apps Script

It’s great to get all the data for each item and all but grabbing such a big hunk of information will slow down our code and, honestly, is a little confusing. Fortunately, we can request only certain fields to be displayed.

Now that we know the properties we want to extract we can include a ‘fields’ parameter into our payload of our request to the Drive API.

How do we write a ‘fields’ parameter string?

  • All fields that you want to be displayed in your string are separated by a comma.
    • "id, mimeType, title"
  • Any nested object fields, for example, "lastModifyingUser":{"picture": "URL"} are separated by a forward slash.
    • "lastModifyingUser/picture/url"
  • Any property within an array of objects is placed between parentheses “()“.
    • "parents(id)"

In our example, our root property is items, which is an array of objects. One of those objects, ‘parents’ contains another array of objects from which we want to extract the ‘id’. Our fields parameter would then look like this:

'fields': items(id, title, mimeType)
Let’s update our code:

Let’s check out our results now:

Much better.

Shared Drives

If you are running this script on Shared Drives, you might be getting an error. You will need to include the following parameters:

You will also need to include supportsAllDrives in your main run function in the first object. More on this later.

Adding Multiple ‘[folder id] in Parents’ queries – the secret sauce!

This is the secret sauce. It will become more apparent when setup the folder iterator later but essentially the reason why our script will be so fast is that we can bank a bunch of folder ids in our query and search multiple folders at one time returning each of the folder’s child items.

This was a pretty cool epiphany for me.

nerd mind blown

We will abstract out the query to a query builder function and update our getFolderItems and test functions.

Add the test function to your file and replace the with the two new functions. Make sure you keep the top comments in so you know where to go to get help when you come back to it in the future, ?.

The Test Function: test_getItemsForFolderArray()

This time around, we are going to create an array of folders.

A bit of foreshadowing here, but we will want to store a dynamic list of parent folders that we want to query. Each array contains an object with an id property and name property.

Note that we have changed the function that we are calling to getItemsForFolderArray() adding our folders as an argument.

Get Items for All Folders in the Query: getItemsForFolderArray()

First, notice that we have renamed the getFolderItem() function to getItemsForFolderArray() to more clearly explain what it does.

On line 17, we have replaced the text query with the variable, “queryString” which can be found on line 13. This variable calls the function createQueryString(folders), taking the folders variable as an argument.

The Query Builder: createQueryString()

Here we are relying on the Google Drive APIs query search term.

Line 13: We start off by creating an empty let variable called “queryString”.

We then need to check two conditions of the incoming folders.

Lines 15-17: If there is only one folder in our ‘folders’ array then we just need to input the folder id along with the ‘in parents’ query.

Lines 19-25: Alternatively, if there is more than one folder in our ‘folders’ array we need to make an ‘or’ statement.

Lines 20 & 24: All ‘or’ statements are batched within parentheses if they must be resolved before another ‘and’ query. For example:

' (id1 in parents or id2 in parents) AND trashed=false'

Line 21: Next, we start a forEach loop to iterate through each of your folders. We also check to ensure we have the index (idx) for each iteration.

Line 22: On each iteration, we first check if we are on the last folder. If we are, we don’t need to append an “OR” to the end of our ‘in parents’ query. However, if with aren’t then we add the “OR” statement.

Line 28: Next, we add any other queries we want to add to our query statement.

Line 31: Lastly, we return our built query string back to the getItemsForFolderArray() function to be added to the payload send to the Google Drive API.

Run the script

Go ahead and run test_getItemsForFolderArray() again.

Notice now that when you run the code, you will see different parent ids in your item list.

If you have found the tutorial helpful, why not shout me a coffee ☕? I'd really appreciate it.

Building the 2d file and Folder Array for the Google Sheet and Updating the ‘folders’ array for the next search

Let’s create a final assisting function before we write our main function. This one is a bit of a doozy.

Our goal is to iterate over the newly collected items from the Drive API call and on each iteration carry out two things:

  1. Create an array of data for each column of the target Google Sheet.
  2. Update the ‘folders’ variable array with any new child folder that we have collected from the recent API request.

Why do these two steps in one function?

Well, you could certainly abstract them into their own functions for clarity, but both functions do need to iterate over the same data, so rather than wasting precious time with two iterations we will run one iteration and extract the necessary data for each array in one hit.

I’ll go into more detail on both of these arrays in a moment, but first, let’s take a look at the code for this function.

The createFileArrays function takes two parameters, the folderArray retrieved from the Google Drive API call and the current folder array that was used in the query of the current API call.

Setup and Loop

Lines 13-16: The first task is to set up the fileArrays object that we will return at the end of the function. This object contains:

  • spreadsheetFormatted: This is the 2d array that will populate the target Google Sheet. You can see how it is structured in lines 32-37.
  • childFolderIds: This is the collection of any folders found on the current call to the Drive API.

On each iteration, these properties will be updated.

Line 19: Here, we use a JavaScript forEach loop to iterate through each of the found items in the selected folders.

Line 21: We will also check the mimeType (the file type) on each iteration to see if it is a folder and if it is, set isFolder to true. This will be referenced in two places later on in the function.

Creating the spreadsheet formatted array

Line 25: As a part of our 2d array for the destination Google Sheet, we will display the parent id and parent name of the file. The tricky part is that in Google Drive each file can have multiple parents. We will need to create a simple array of all parent IDs of the file and iterate over them to compare them against the list of folder IDs.

Line 26: Next, we will use the JavaScript ‘find’ method to search for any id that is included in the array of file parent folder Ids. This will return the matching parent folder (with its id and name) if it is found or a falsy ‘undefined’ if one does not exist in the list.

The results will then be used in the spreadsheet array.

It is undoubtedly improbable for the current list of folder ids to not be in the parent list of ids for the currently iterated items. This is because they were extracted from the ‘folders’ list.

Line 28: For the parent folder id column of our Google Sheet it would be helpful to provide a hyperlink to the folder where the item exists.

Here, we use the HYPERLINK Google Sheets function applying the standard Google Drive URL with the appended parent folder ID and then using the folder ID as the label.

Line 30: Next, we create either a file emoji or folder emoji for our image cell using the isFolder boolean variable generated on line 21. This will provide a convenient visual queue to identify the nature of the item.

Lines 31-38: Now that we have all the components we need to build our array we set them into the fileData array variable.

Line 40: Finally, we concatenate the newly created array to the existing fileArrays.spreadsheetFormatted array.

Create and Publish Google Workspace Add-ons with Apps Script Course 300px

Creating the child folders list

Every time we search over our Google Drive’s selected IDs it is likely that we will collect more folders to search. In this section of the function, we need to create a new array of folders from the items we have just collected.

Lines 44-51: If the currently iterated item is a folder (isFolder) is set to true, then we need to add it to our fileArrays.childFoldersIds array.

Test the function

Copy and paste the code below. You can also paste the folder array from your  test_getItemsForFolderArray() function that you ran earlier.

The first logged item will be the raw response data from the Drive API.

The next one will be the current array of 2d data destined for our Google Sheet.

The last log will be the new child folders that we will need to query on our next call to the Drive API.

Get All Files and Folders in The Parent Folder directory tree

In this section, we will create our main run function that will iterate over all files and functions in the directory tree.

Here is the main code for this function:

The Main Function Variables

Line 5: Out of curiosity, we want to check to see how long it will take for the script to run. We use the JavaScript time method with the console here. We will add the end-time method at the end of the script.

Line 8: Here we add our parent folder id. Go ahead and update the script to add your own folder id now.

Line 10: The folderData  object variable will store the response from the Drive API and will be updated after each call to the API.

Line 11: The directoryArray variable stores the total found items in the directory tree as a 2d array to be added to the destination Google Sheets. It will be concatenated on each iteration of the while loop.

Lines 12-17: We are already familiar with the folders variable in our testing of the helper functions. Here we set up the parent folder as our first folder to search. Adding its array to the id.

For the name, we call the Drive  API once using the ‘get’ method. We specify the field “title” only and then retrieve the title of the folder. Alternatively, you could paste in the folder name yourself and save a call to the API.

Note that if you are using Shared Drives you will also need to include "supportsAllDrives": true to the parameters to request the folder name. So should look like this:

Drive.Files.get(rootId, { 'fields': 'title', "supportsAllDrives": true }).title

Looping over the folders. What’s happening?

So as I alluded to earlier, we aren’t actually, calling the Drive API list method on each folder. Instead on each call to the API we collect a list of folders and add them to a folders list then we will run a query on all of the folders in our list (array).

Iterating over multiple folders at once in Google Drive with Apps Script


Line 20: Starts the main while loop. Here we check if there is a least one folder item in our folders array, by checking the length of the array. If there is, then we continue.

Remember, the folders array is updated every time we make a list request to the Google Drive API. So when our array runs out of folders, then we can stop the while loop.

Line 22: Here we call the getItemsForFolderArray() function taking the folders array as an argument. This will call the Drive API and return the current list of items found in all of the folders in the folders  array and store it in the folderData object.

Line 23: Remember, that the folderData object contains data on the Drive API list process. This includes the item property which is an array of all found items from the list query. We will temporarily store these items in the items array.

Our next task is to store both our data that is going in the Spreadsheet and also update the folders array.

Line 27: First, we call the createItemsArrays() function applying the items and folders arrays as arguments. This will return the childFolderIds array and spreadsheetFormatted array assigning it to the variable itemArrays.

Line 28: Next, we replace the folders array with our new list of folders to query.

Line 29: Then, concatenate the directoryArray with our newly found list of items.

Updating the Google Sheet with our Items List

Our last major task for this main run function is to update our Google Sheet.

Line 34: First we call the active spreadsheet bound to this Apps Script project invoking the SpreadsheetApp class and calling the getActiveSpreadsheet() method.

You could also use the openById() method to add the data to another specific spreadsheet.

Next, we chain some more methods:

Line 35: This gets the sheet tab by its name using the getSheetByName() method.

Line 36: We then need to select a range of cells to add our data. This will be equal to the number of columns and rows in our 2d array. Here we call the getRange() method which has an optional 4 integer insert parameter setup:

  1. Start Row: This is row 2 below our header.
  2. Start Column: This is Column A or column number 1.
  3. Row depth: How many rows we will be adding our data to. We can calculate this by getting the length of the main, outer, 2d array of the directoryArray.
  4. Column width: The number of columns across on each row we will be adding. To get this value, we can get the length of the zeroeth item in the inner array.

Line 37: Finally, we add our array values to the Google Sheet range with the setValues() method adding the directoryArray as its argument.

Run your code

After updating your parent folder and saving your script, you should be good to go running your code and see the results.

Go ahead and check out your results in your connected Google Sheet!

What about edge cases?

By now some of you may have been vigorously rage-correcting your glasses thinking, ‘This code sucks! Yagi hasn’t even handled for huge amounts of items in a folder! What happens if you are querying a large number of folders all at once?! Will it break the query? What if the code times out?! Argh!^n.”

Well first, that’s a bit rude mate. Second, now that we have our basic structure sorted out let’s go back into our code and update it one at a time.

One thing I will leave out is handling for time-outs. It’s a big subject with many approaches. I discuss this a little more later when we get to it.

standing on the edge

Next Page Tokens: Handling for a large item list

The Google Drive API file list is limited to returning a maximum of 100 items per request. I guess the list method is considered a batch request because it contains limitations in batch requests.

Fortunately, each list request can provide a nextPageToken property with a unique id that you can add to your next API request and get to the next page. If the total number of queries is less than the maximum number of requests then the nextPageToken property will not be present.

With this in mind, we can go back and update the getFileAndFolderIds() function and getItemsForFolderArray() function.


Our first task is to retrieve the page token from the Drive API query.

Check out the updated  getItemsForFolderArray() function:

Lines 8 & 12: You can see now we have an extra parameter. The pageToken. This will either be a token string for the next page or null.

Line 19: Next, we need to include the nextPageToken field into the fields property of the payload to ensure that it is returned when it is available.

Line 23: Lastly, we check if we have a page token, for the next page. If we do, then we know that we are looking at the next page of the current query of folders not a new query of folders. We then add the page token to our payload to be sent as a request to the Drive API.


Now we need to create a loop whenever we have a page token to iterate over the current query of folders. Check out our updated code:

Lines 21 & 33: First, we create a JavaScript do-while loop. We will need to carry out the first request to the API before we start the loop so we need to make a ‘do’ statement first. Then, while a page token exists, we need to continue to call the API until we have run out of pages.

Line 22 & 29: Next, we moved out our items array and called it before this do-while loop. This way we can append to it and build up the items array with new items as they come in from the consecutive page requests.

Lines 10 & 31: Lastly, we add a let variable, pageToken, that we update on line 31. If the page token is retrievable, it will return a token string otherwise the variable will store null.

Testing the page token iterator

We can test the page token iterator by adding the maxResults parameter to the payload variable in the getItemsForFolderArray() function.

Try setting the max results to something really small like 5 or 10. Like this:

'maxResults' = 10

Now run the main getFileAndFolderIds() script and note how long the script took. It should have taken quite a bit longer. Don’t forget to remove this line when you are done testing.

Another way of reviewing this process is to use the Apps Script IDE debugger and mark the ‘pagetoken = line‘ you can then review the debugger data to see what data was collected.

Max Query Length: Is the query too long

With the way our query works, this edge case is less likely to occur but is possible enough that it is worth checking for.

Hypothetically, a query may have a maximum string length of characters.

This isn’t something I had a chance to personally measure but the maximum query length may be a little under 8,000 characters if we can assume our API request behaves the same way as a URL query, well, according to the Improve Performance documentation. The Stackoverflowians have mixed views on this citing a query characters length of between 29949 and 29999 for one commenter and 7340 for another.

Probably our best bet here is to just set a variable with a max number of queries for ‘[folder is] in parents‘ that we can generate, and modify it in the future should we confront an error. Or, you know, test the length properly ?‍♂️.

Get the max number of ‘in parent’ queries

Add the following code to your file to get the maximum number of folder queries we should add per request.

Basically, we are setting our maximum hypothetical query string length. Then we subtract the remaining part of the query from the length before dividing that value by the average length of a ‘[folder is] in parents‘ query.

This will give us the total number of folder queries we can add to a query request before it throws a wobbly.

With this value in hand, let’s update our code.

getFilesAndFolderIds() update to handle max query string length

Line 4: First we set a maximum number of folders that we want to add to our query. You can see that I added ‘5’ above for testing, but I would return to ‘598’ for future queries.

Lines 16-18: Next, we create an array that will temporarily store any remaining folders that we did not have enough room to add to our query.

Lines 26-33: Before making our API request we check the total number of folders that we need to query. If the total number (array length) exceeds our maxNumOfFoldersPerQuery value then we need to store the remainder in foldersRemaining and query the rest.

Line 50-52: Once we have made our request to the API we update the folders array with the remaining folders and new folders that we collected with our query.

Go ahead and test the code again now, with a small number in the maxNumOfFoldersPerQuery variable. Then run the function.

You could also console log the remaining folders array to see what is left over.

Rest the maxNumOfFoldersPerQuery variable with the larger value in the comments or your own custom value.

Not Getting All the Files And Folders Shared With Me in a Shared Drive

In some cases when working in Google Drive, the script above may not display ALL files and folders. This is because, by default the query is set to what the user has created or is an editor of.

To see all files and folders created by all users in a Shared Drive you will need to also declare the corpora (the dataset) to ‘drive’ and then declare that share drive id to search within in ‘driveId’.

In the script, you should then add the following to the payload of each Drive.Files.List call:


Some Edgier Edge Cases

So this is about as far as I want to go in this tutorial, but if you want to go further into the weeds you might want to consider a few other edge cases.


Roughly, your script will time out after about 6 minutes of running this script. So far, I have yet to have a problem with the script timing out on large directories due to its solid performance. However, on a less performant version, I did and had to handle for it.

Create and Publish Google Workspace Add-ons with Apps Script Course 300px

Some alternatives and workaround you might want to consider are:

QUOTAs and limitations

According to the docs, Google Drive API requests are limited to:

  • 20,000 queries per 100 seconds.
  • 20,000 Per 100 seconds per user.

That is an awful lot of queries.


“…blazingly fast…”, Jeff Delaney,

As you can see the code we build together is a, dare I say, ‘blazingly fast’, approach to a glacial problem of retrieving files and folders from a Google Drive.

I really love to hear how you used the code in your own project. Did you extend it further to run bulk updates or deletes? Did you add new fields? Did you use it to duplicate a directory? Let me know in the comments below!

Create and Publish a Google Workspace Add-on with Apps Script Course

Need help with Google Workspace development?

My team of experts can help you with all of your needs, from custom app development to integrations and security. We have a proven track record of success in helping businesses of all sizes get the most out of Google Workspace.

Schedule a free consultation today to discuss your needs and get started or learn more about our services here.


  • 2024-05-11
    • Added information on getting other users files and folders that are shared with you in a Shared Drive using the corpora and driveId parameters. Thanks to Harold Herrera Sánchez and Bob Neville for enquiring about this.
  • 2023-07-03
    • Removed “_v2” artifact from createFileArrays() function.
    • Special thanks to Jes for the find.
  • 2023-06-22
    • Updated Shared Drives section to include ‘includeItemsFromAllDrives’: true.
    • Added a note to The Main Function Variables to ensure that sharedDrives:true is added to the Drive.File.get request.
    • Special thanks to Edward for bringing this up.


33 thoughts on “List all files and folders in a selected folder’s directory tree in Google Drive: Apps Script”

  1. Wow. Another very well documented and complete analysis. Your detailed write-ups really help others understand. Thanks for taking the time. I know it’s not easy but it is very much appreciated.

  2. Ok, I think I also need to add “supportsAllDrives” to getFileAndFolderIds()

    So I added here, which got past the “file not found” error:

    let folders = [
    name: Drive.Files.get(rootId, { ‘fields’: ‘title’, “supportsAllDrives”: true }).title,
    id: rootId

    However, it’s resulting in no results.

    1. After some mucking around and testing…

      For non-shared drives, this works beautifully and is lightning fast.

      For Shared drives, after adding two parameters:
      ‘supportsAllDrives’: true
      ‘includeItemsFromAllDrives’: true

      I’m able to get it to list the files in the root folder, and the subfolders, but not the files in the subfolders.

      1. Hi Edward,

        Thanks for the heads up. Yes you are right! You will need to add both supportsAllDrives:true and includeItemsFromAllDrives in the payload for getItemsForFolderArray().

        In the initial lookup for the root id file name in you will only need to add supportsAllDrives:true.

        I’ve gone ahead and updated the tutorial and added the notes to the changelog with a special thanks to you for catching this one.



  3. Thank you so much for this! I’m having trouble getting it to work on a Shared Drive folder though. I keep getting a file not found error: “API call to drive.files.get failed with error: File not found”.

    I’m sure I have access and I’m sure I have the folder ID correct. And I did add the supportAllDrives parameter (I add it here, right?

    const payload =
    ‘q’: '${folderId}' in parents and trashed=false,
    ‘fields’: items(id, title, mimeType),
    ‘supportsAllDrives’: true

  4. Hi Scott!

    Now that Google has retired the Drive app and replaced it with DriveApp, is it worth updating this script for DriveApp? I know not all the functions of Drive work (or even exist) the same way in DriveApp. What do you feel is the best way to replicate this script’s great function and speed?

    1. Hi Mike.

      What makes you think Drive API has been sunset?

  5. Wow, thanks for another awesome, useful, inspiring and indepth solution.

    We’re a bunch of non-IT people doing GAS solutions for our poor colleagues who don’t know code or how to make their work life so much lighter. We will surely be using this BLAZINGLY fast piece in our automation solutions to ease life for even more colleagues at work.

    I think there’s a leftover reference to a getCurrentDirectory(folders) function in en early test_getItemsForFolderArray() function. Also, some places in the early explainers, the createQueryString() function is renamed to createQueryString_v2().

    1. Hi Jes,

      Glad you found the tutorial useful and great find on that ‘_v2’ artifact, I’ve remove it now.



  6. Hi,

    Great app and blazingly fast. I’ve been able to filter the list based on starred items, but I’d also like to retrieve the comments if any attached to file (at least the first comment on reach file, if not all).

    Can’t figure out how to do this. Any help and advice would be greatly appreciated.

    Many thanks,

  7. This is absolutly brilliant! Cant’ believe this isnt the top result in google search!! Now I can look through all files and folder to do want I need. So fast. the was so incredibly slow. Thank you a lot!!!

  8. Hi Yagi!
    I was messing arround with appscript with folderiterators. Seems this is more efficient, but for a newbie like me it’s there the possibility to get the full functional code? Just to copy/paste and change the folder ID.

    Maybe is my lack of experience, but for me is complicated to follow the explanation with all the changes. I see you want to make a step-by-step tutorial like you did it.

    Note: When you add the – ‘fields’: items(id, title, mimeType) – the boxcode below is collapsed and can’t see the code properly.

    Thanks for your post ?

    1. Hi Tots,

      I generally prefer to make tutorials that peeps can follow along and learn by building the product on their own. You can definitely (An many have) build this by following the tutorial.

      But I agree, this takes time and if you need a product for your project to deploy quickly then, I am happy to sell the full code as a product.

      Send me a message on my ‘Contact Us’ page if that’s what you need.


      1. Thanks for your offering, Yagi
        However I just was messing arround with AppScript, there is not a objetive I need to acomplish in short term.
        I will keep playing 🙂

  9. Great video! Really has helped me out with a project.
    Curious if there is a way to easily generate a breadcrumb string. I have a lot of folders and subfolders, several of which are named the same thing (i.e. – years (2020, 2021,…) within different subfolders) so would be great to be able to generate the full file/folder hierarchy within a single string.

    1. Thanks, Ed.

      You could iterate through the parent folder for each file (There can be multiple parent folders) and join them together in a string.



  10. Very Fast! But some “big folder” (alot of files and subfolders) get “Error 400 (Bad Request)!”
    (HttpResponseException: Response Code: 400. Message: ) Can I fix it?

    1. Hi Petro,

      There is a hard limit of 100 items per request. Do you still get error when you implement a next page token like I mention here?

      1. Hello Yagi,
        Problem fixed by limited “maxNumOfFoldersPerQuery” to “297” or less.

        Thanks alot for your big work!

  11. Hello Yagi,
    Awesome tutorial ! Thanks a lot for your work !
    I am trying to get some more metadata. I managed to get the owner emailadress. Howerver I would have also loved to get the viewers and editors, as it is possible with the class FILE (file.getViewers() and file.getEditors()). I am affraid it is not doable when I look into the input of the JSON file.
    Could you confirm this ? Or is there a smart way to do it ?
    Best regards from France.

    1. Thanks, Brian!

      You will need to use the Permissions class for this one:

      URL Fetch App – fetchAll() might be handy for this approach:

      You can also track some activity with the file with the Drive Activity Service:

      I hope this helps.

      ~ Yagi

  12. Hi Yagi,

    This was a great tutorial.

    I have 1 question: where do I put the ‘includeItemsFromAllDrives’: true in the script so I can use it with a shared drive?

    1. Thanks. You can add it to the payload object.

  13. Hi Yagi,

    I want to include the owners email Address in my file. I know I have to change both the payload and the fileData constants. I’ve tried a few things, but there is clearly something I am not quite getting right. If you could steer me in the right direction, I’d appreciate it.

    This script is going to be super helpful for a Drive clean-up project I am working on for a non-profit. It is going to save us a bunch of time, and let us do somethings quickly that we probably would have not bothered to do.

    1. In the fields of the payload you can add the ‘owners’ array type this will be inside the existing items array string e.g. items(... , owners(emailAddress))

      User Object

      In the createFileArrays function insert the Owner email row. To access the row you will need to use the file.owners[0] property.

  14. Thank you for such a detailed tutorial! For one of the applications that I just finished, I used an iterative method involving DriveApp to drill down and reconstruct the directory tree, and the function is as slow as molasses, so I am hoping that this approach will speed things up. However, it seems that Google dramatically altered the Drive API since you wrote this tutorial (or alternatively, my google account performs differently from yours??): When I run the following commands:
    const rootId = ‘1_3kdW12345678abcdefgHIJKLM’; // <== made up, obviously!
    var test = Drive.Files.list({
    ‘q’:'$(rootId}' in parents and trashed=false,

    I get a response that is significantly different from what you report here. my response is something like:
    { kind: ‘drive#fileList’,
    files: <—- not items but files !!!
    [ { kind: ‘drive#file’,
    mimeType: ‘application/’,
    name: ‘main’, <—— not title but name!!
    id: ‘123456769abcdefghijk’ },
    {name: ‘example’,
    kind: ‘drive#file’,
    id: ‘ABCDEFGHIJK123454566’,
    mimeType: ‘application/’ } ],
    incompleteSearch: false }

    is it possible that this API could have changed so dramatically in, what, less than a year? Or more likely, what am I doing incorrectly in my usage of the API call? Thanks!

    1. Hi Pamela,

      A couple of things that might help you:
      1. I looks like you might be using V3 of the Drive API rather than V2. Click the ‘Drive’ item under ‘Services’ in the sidebar of the IDE and change it to V2. V3 was recently release to Google Apps Script a few months ago. Both versions have their pros and cons.
      I mention that V2 should be used in ‘The Starter Sheet’ section . It’s a comprehensive guide so easy to miss a few things along the way.

      1. I noticed that the query property was not quite right. This may have just occurred during the writing of your comment, but just in case, it should look a little like this: 'q':'${rootId}' in parents and trashed=false,

      Happy coding!


      1. Thanks! And indeed, I was using whatever the default version is, which appears to be V3. The query above indeed had a typo! (which was introduced in writing the comment and was not thankfully in my test code.)

  15. Hi! This looks like a great tool. I purchased it (busy and not a very competent coder), but I seem to be having trouble getting the tool to return recursive results.

    It will return direct children of the folder I specify, but not children of subfolders, etc. I believe from the documentation, this is supposed to be possible. Please advise, and thanks very much!!

Leave a Reply