How do I perform a function on ALL the children (and subchildren, etc) of a single folder? - google-drive-api

I have written a (successful) function which takes a Google Doc as its input, and makes certain changes to its body text.
Here's where I'm stumped: how do I perform THAT function on ALL the Google Docs in a given folder? When I say "all," what I mean is:
I want to INCLUDE the folder's children, sub-children, sub-sub-children. (I tried using myFolder.getFiles(), but this is too narrow: it only gets the docs that are the direct children of the folder -- not the sub-children, etc.)
I want to OMIT any files that are NOT in this folder. (I tried using DriveApp.getFiles(), but this is too broad: it gets ALL the docs in my Drive.)
Thanks!

The relation in Google Drive is from children to parent. This means that each file has a parameter called "Parents" where it stores the id of the folders where it belongs. Instead of the parent having a list of children.
When retrieving the list of files from a folder you are selecting all the files that have that folder id in the 'parents' parameter.
Because of this you won't be able to query all the children belonging to a parent folder.
You will have to get all the children from a folder, and look for the folders in it and then get the children for each one of those folders and so on.

Related

Google Drive apply label to all files in folder/subfolder

My organization is requiring that all files in Drive have one of several labels applied to them. It seems you can multi-select up to 100 files and apply a label, but is there any way to apply a label to all files in a folder/subfolder? Our folders are organized alphabetically, so there are only a handful of files in each subfolder, which leads to a lot of extra manual work going in and out of each folder to apply the label rather than just propagating it down to all files in the folder structure.
If you can identify conditions based on which these files will be labeled, you could use DLP rules (https://support.google.com/a/answer/9655387?hl=en&ref_topic=9646660)
For example if you want to label as Confidential all files which include in the filename the world "Payments", you can create a rule with a regular expression like:
(\W|^)[Pp]ayment[s]{0,1}(\W|$), and assign the label "Confidential" automatically ,to existing and new files.

How to create folders recursively in googledrive through api?

For example, I'm going to upload a file scenery.jpg to /images/2020/03/18/ directory, if I upload to OneDrive, the upload url going to be like this:
https://graph.microsoft.com/v1.0/me/drive/root:/images/2020/03/18/scenery.jpg
I don't have to know if the images folder, the 2020, 03 and 18 folder exists or not, OneDrive will auto create it recursively, acting like Object-based Storage.
But now, I'm going to upload it to GoogleDrive and GoogleDrive seems can't create folders recursively(as far as I know, see Create and populate folders), now I have 2 questions:
1、Is that I have to check if these folders exists one by one to make sure if I have to create these folders?
/images/
/images/2020/
/images/2020/03/
/images/2020/03/18/
2、If none of above folder exists, is that I have to create these four folders one by one(means request api four times)?
Anyone who did this before? I hope what I assume is wrong, because it's too complicated to do it in this way.
Unfortunately you are correct
Google handles file and folder hierarchy in a different way and indeed the only way create / list nested files and folders is to iterate recursively.
Also, if you want to know if a file / folder already exists with the method Files:get, you need to know the file / folder ID, rather than just the name. If you do not know the ID, than you need to list all files on your drive / (unless you specify a certain folder as the parent folder, e.g. '1234567' in parents with the query parameter q).
The same applies for creation. If you create a folder which you want to be a subfolder of a different parent folder - you also need to create the parent folder.
However, it is not as complicated as you may think.
Here is one of many available samples of how to list the contents of all subfolders and subfolders of subfolders dynamically - in your case you would just need to add the condition to create a certain folder if it is not contained in the list.
You would need to take some time to study the working principle of Drive API, however once you get an understanding it is not complicated.

get files list of particular mimetype in specified directory

I'm successfully getting files in specified directory using request:
GET https://www.googleapis.com/drive/v3/files?q="1bmCj4FYUVVuxq6sUnGFKrizAjwtbq7XD"+in+parents
(but it includes files of all mimetypes).
Also I'm successfully getting files of specified mimetype using request:
GET https://www.googleapis.com/drive/v3/files?q=mimeType%3D%27application%2Fvnd.google-apps.spreadsheet%27
(but it includes files of all my directories).
Now how do I get files of particular mimetype in specified directory? I tried something like
GET https://www.googleapis.com/drive/v3/files?q="1bmCj4FYUVVuxq6sUnGFKrizAjwtbq7XD"+in+parents&mimeType%3D%27application%2Fvnd.google-apps.spreadsheet%27
or
GET https://www.googleapis.com/drive/v3/files?q=mimeType%3D%27application%2Fvnd.google-apps.spreadsheet%27&"1bmCj4FYUVVuxq6sUnGFKrizAjwtbq7XD"+in+parents
though it considers only the first parameter, but not both parameters. Please advise.
For initial question: (Solved)
You want to retrieve the files with the specific mimeType in a specific folder.
If my understanding is correct, for query, how about modifying as follows? Please use and for your case.
'1bmCj4FYUVVuxq6sUnGFKrizAjwtbq7XD' in parents and mimeType='application/vnd.google-apps.spreadsheet'
So can you try to use as following endpoint?
GET https://www.googleapis.com/drive/v3/files?q=%271bmCj4FYUVVuxq6sUnGFKrizAjwtbq7XD%27%20in%20parents%20and%20mimeType%3d%27application%2fvnd%2egoogle%2dapps%2espreadsheet%27
Reference:
Search for Files
If I misunderstand your issue, please tell me. I would like to modify it.
For 2nd question: (Solved)
For example, if you want to retrieve files from 2 folders, please use the following query. In this case, files from folder ID 1 and folder ID 2 are retrieved.
'### folder ID 1 ###' in parents or '### folder ID 2 ###' in parents
For 3rd question: (Solved)
When you want to retrieve files with the mimeType of application/vnd.google-apps.spreadsheet in several folders, please try to use the following query.
('1bmCj4FYUVVuxq6sUnGFKrizAjwtbq7XD' in parents or '1QR_Thw-5xZmGVZAkUeeDXQ4KhA55t2Pm' in parents) and mimeType='application/vnd.google-apps.spreadsheet'
For 4th question: (Solved)
Unfortunately, the file list cannot be directly retrieved by the folder name using the query. Because the same folder names can be existing in Google Drive. So it is required to use the following flow.
Convert the folder name to folder ID using the following query. If several folders are included in the result, please retrieve one of them.
name='### folder name ###' and mimeType='application/vnd.google-apps.folder' and trashed=false
Retrieve file list using the converted folder ID. You can use the query from 1st to 3rd answer.

google apps script - File getParents() and makeCopy(), removeFromFolder()

The reference about File.getParents() and File.makeCopy is unclear.
For File.getParents, what will be returned(are they all ancestor folders along with the path or are they all parent folders because File is possible to have multiple parent folders?), and in what order?
For File.makeCopy, which folder will the new file be located if File has multiple parents?
From some testing, it seems getParents always put Root folder as the last element in returned array if root folder is one of the parents no matter when it is added to parent list, other folders are randomly ordered. makeCopy always put the new file into Root folder even the original file has no Root as its parent.
EDIT: Someone said "The DriveApp Service was updated August 20, 2013, with new methods File.makeCopy(destination) and File.makeCopy(name, destination), which allow scripts to specify a folder to which a file should be copied." in this post. but i just tested it does not work as of today.
Also there is a delay for removeFromFolder() to take effect. Sometime you can see file located both at root folder and its designated foler.
Please explain.
Your observations are correct , Root is always the top parent of any file (that's why it called "root") unless you remove it explicitely (see this post for example) and when you copy (or create) a file, this file is always in Root, no matter where it comes from and it's up to you to move it at the right place (many posts around here on that subject) EXCEPT when you make a copy using folder.createFile() and similar... in that case the file is only present it its parent folder.

Is there any easy way to get folderID based on a given path?

Box api is implemented to be RESTful. and most supported methods are based on ids, folder_id or file_id.
As a very beginning start point, a root folder id, 0, stands for the root directory /All Files/.
from there (fold_id = 0), I can loop through all sub folders and find folder id for certain target folder.
or I can send search request to "https://api.box.com/2.0/search?query=target_folder_name", and process the response to locate target folder.
The former approach may need multiple list-folder-item requests, and the latter approach might be slow because the search is not just for folder/file name but also for other attributes of folder/file and even file content.
I am wondering if there is an easy way to find folder id for certain folder with a given path, such as "/All Files/MyFolder_A/Project_11".
Thank you very much for any help.
To the best of my knowledge, walking the folder tree (as you've suggested) is still the fastest way to get the ID of a particular file/folder. (See also this question: Get file ID of a given path.)