Reputation: 21
I have logged an issue with Google's Issue Tracker about the Folder.moveTo(destination)
function not working, as it appears to be a bug. Feel free to star the issue to give it a bump!
https://issuetracker.google.com/issues/163080678
I am trying to provide a "one click" way of moving folders in Google Drive via an add-on (which appears in both Drive and Gmail). For context, each "folder" in this case is a matter, and the "one click" will move the folder (containing all the relevant documents to that matter) from the "open" folder to the "closed" folder. However, I am getting confusing and unhelpful errors every way I try to achieve this.
Note: all of these folders are in a Shared Team Drive. I'm aware that this places some limitations on what the DriveApp Service and Drive API can do, but I'm crossing all my fingers and toes that it's not just an inherent limitation and that there is a workaround!
I have already read the following:
But they did not solve my problem (noting that addFile()
, addFolder()
, removeFile()
and removeFolder()
have been deprecated recently and so are no longer available as the answers above would suggest).
My expectation is that when the user hits the "Close" button in the add-on, it will move the relevant folder (selected at a previous stage in the add-on) from the "open" folder, to the "closed" folder (which sit next to each other at the same level in the folder hierarchy). To be clear, I'm hoping that it will move the folder, not duplicate it in the target folder and then delete the original from the original parent folder.
See specific error messages below, but generally speaking, when the user clicks the "Close" button, I get an error right away, and nothing happens to the folder.
Taking the Google documentation at face-value, I first attempted to use Folder.moveTo(destination)
as below:
function moveFolder() {
var folderToMove = DriveApp.getFolderById(MOVE_FOLDER_ID);
var destinationFolder = DriveApp.getFolderById(DESTINATION_FOLDER_ID);
folderToMove.moveTo(destinationFolder);
}
However, on running this, I get the error message: Exception: Unexpected error while getting the method or property moveTo on object DriveApp.Folder.
Failing to fix the above, I tried the Advanced Drive feature of Google Apps Script, and attempted to use Drive.Files.update()
(documentation here). My code looks like this:
function moveFolder() {
Drive.Files.update({parents: [{id: DESTINATION_FOLDER_ID}]}, MOVE_FOLDER_ID);
}
I also tried a variation including the optional paramter supportsAllDrives
, as below:
function moveFolder() {
Drive.Files.update({supportsAllDrives: true, parents: [{id: DESTINATION_FOLDER_ID}]}, MOVE_FOLDER_ID);
}
However, both variations give the error: GoogleJsonResponseException: API call to drive.files.update failed with error: File not found: [fileId]
, where [fileId]
is the actual Google Drive ID of the folder being moved.
I have confirmed in both attempts 1 and 2, by using various other functions I know do work (like adding customer properties with Drive.Properties
and renaming the folder using DriveApp), that the folders themselves are definitely being passed through correctly and are able to be manipulated programmatically. Ie, the folder definitely exists, and using the URL in the browser, can definitely be found using that Drive ID.
Upvotes: 2
Views: 2940
Reputation: 21
Using DriveApp Methods only, you can also migrate a folder by
hint: If multi-parenting applies to the subfolders within the folder that is migrated, you need to include a check in the code above in order to avoid creating duplicate folders.
// execute this function
function run_me() {
var folderId = 'ID_OF_FOLDER_TO_BE_MIGRATED'; // some folder (located in My Drive or Shared Drive)
var targetParentId = 'ID_OF_TARGET_PARENT_FOLDER'; // a folder in a Shared Drive
var folder = DriveApp.getFolderById(folderId);
var parent = DriveApp.getFolderById(targetParentId);
migrateFolderToSharedDrive(folder,parent); // copy folders and move files
folder.setTrashed(true); // trash original folder
}
// main function (recursive)
function migrateFolderToSharedDrive(folder,parent) {
var copiedFolder = parent.createFolder(folder.getName()).setDescription('previous Id: '+folder.getId());
Logger.log('Folder created with id %s in parent %s',copiedFolder.getId(),parent.getId());
// move files
var files = folder.getFiles();
while (files.hasNext()) {
Logger.log('File with id %s moved to %s', files.next().moveTo(copiedFolder).getId(), copiedFolder.getId())
}
// recurse any subfolders
var childfolders = folder.getFolders();
while (childfolders.hasNext()) {
var child = childfolders.next();
Logger.log('processing subfolder %s',child.getId());
migrateFolderToSharedDrive(child,copiedFolder); // recursive call
}
}
Upvotes: 1
Reputation: 21
Rather than moving a folder directly you could a) create an "equivalent" in the new location in your shared drive, b) move its files to the new folder from a using moveTo() and c) delete the original folder after completely migrated. This will of course change the id of your folders, but it works for shared drives and also with folders from MyDrive that should be migrated to a shared drive
Please note this makes use of Advanced Drive Service v2 (enable it in Apps Script):
// function to copy a folder e.g. to a shared drive
function copyFolderToSharedDrive(folderTitle,folderId,targetParentId) {
var optionalArgs={supportsAllDrives: true};
var resource = {
title: folderTitle + '_copy', // adjust according to your needs
mimeType: 'application/vnd.google-apps.folder',
parents:[{
"id": targetParentId, // some folder in a shared drive
}],
description: folderId // optional, to back reference the source Folder
}
var migratedFolder = Drive.Files.insert(resource, null, optionalArgs);
Logger.log(migratedFolder.id);
// Optional: post-process original folder, e.g. trash it
// ...
}
Drawback when moving from My Drive until Single Parent Model has been enforced in My Drive: You need to check for multiple 'addings' of your subfolders so as to avoid creating duplicate folders.
Upvotes: 1