简体   繁体   中英

How to move a folder in Google Drive using Google Apps Script

EDIT

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


Background

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).


Expected Result

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.

Actual Result

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.


Attempt 1 - Folder.moveTo(destination)

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.

Attempt 2 - Drive.Files.update()

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.

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.

Using DriveApp Methods only, you can also migrate a folder by

  1. creating the folder in shared drive
  2. move files to the created folders
  3. recurse for any sub-folders
  4. trash original folder that is moved.

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
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM