// Drive · Apps Script

Move a file to another folder in Google Drive.

Use DriveApp in Google Apps Script to reliably move a file to a new folder with file.moveTo(folder), avoiding the old addToFolder/removeFromFolder trap that silently left files in both places.

I want to write an Apps Script that moves a Google Drive file into a different folder without duplicating it or leaving it in the original location.

The script

copy · paste · trigger
moveFile.gs
Apps Script
// Move a file to a target folder by their Drive IDs.
// Requires Drive scope: https://www.googleapis.com/auth/drive

function moveFileToFolder(fileId, targetFolderId) {
  var file = DriveApp.getFileById(fileId);
  var targetFolder = DriveApp.getFolderById(targetFolderId);
  file.moveTo(targetFolder);
}

// Quick manual test — paste real IDs before running.
function testMove() {
  var FILE_ID   = 'YOUR_FILE_ID_HERE';
  var FOLDER_ID = 'YOUR_FOLDER_ID_HERE';
  moveFileToFolder(FILE_ID, FOLDER_ID);
  Logger.log('Done. File is now only in the target folder.');
}

Need a variant? Gnaw writes a custom version from one sentence — fields, triggers, edge cases handled.

Walkthrough

Why moveTo() exists and what it actually does

Google Drive used to allow a file to have multiple parent folders simultaneously. The old pattern was to call file.addToFolder(newFolder) followed by file.removeFromFolder(oldFolder). The problem: if you got the order wrong, or if removeFromFolder threw an exception, the file ended up living in both folders with no error logged. I have watched this bite people who were tidying up processed files in a pipeline — the cleanup step succeeded, the file sat in the original folder for weeks, and nobody noticed until storage was audited.

DriveApp.File.moveTo(destination) was added to the Apps Script Drive service to make this atomic. It sets exactly one parent on the file — the destination folder — and removes all previous parents in the same call. There is no partial state to recover from. The method has been available since the Drive API v3 migration and is the documented replacement for the addToFolder/removeFromFolder pair.

The return type is void; moveTo does not return the file object, so you cannot chain it. If you need a reference to the file after moving, keep the variable you already have — the file object itself remains valid after the move.

Getting the IDs from a Drive URL

Both DriveApp.getFileById and DriveApp.getFolderById take the Drive resource ID, not the human-readable name. For a file, the ID is the long alphanumeric segment in the URL: in https://drive.google.com/file/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms/view, the ID is 1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms. For a folder, open the folder in Drive and copy the last path segment from the URL.

If you are building a script that needs to find a folder by name rather than ID, use DriveApp.getFoldersByName('Processed') which returns a FolderIterator. Call .hasNext() before .next() — if the folder does not exist, .next() throws rather than returning null. Name-based lookup is fragile in shared drives where names are not unique; ID-based lookup is always safer for production scripts.

Scope requirements and common authorization errors

moveTo requires the full Drive scope: https://www.googleapis.com/auth/drive. The narrower read-only scope https://www.googleapis.com/auth/drive.readonly will let getFileById succeed but moveTo will throw Exception: You do not have permission to perform that action. If you see that error despite owning the file, check the OAuth consent screen and verify the script is not locked to the restricted drive.file scope, which only covers files the script itself created.

In a bound script (one attached to a Sheet or Doc), Apps Script infers scopes from the code it detects at save time. If the editor flags moveTo as needing an additional scope, you can pin the scope explicitly in appsscript.json under the oauthScopes array. Standalone scripts in the legacy editor sometimes cache the old scope list; running Reauthorize from the script editor menu clears it.

Want a custom version?

Describe your sheet and the rule you want. Gnaw writes the Apps Script — fields, triggers, edge cases — in one shot.

FAQ

4 questions
Does moveTo work on files in a shared drive (Team Drive)?
Yes, with one constraint: the caller must have Contributor access (not just Viewer or Commenter) on both the file and the destination folder. If either lives in a shared drive where the script runner only has view access, moveTo throws a permissions error. Shared drive files cannot be moved to My Drive or between shared drives — only within the same shared drive.
I used addToFolder and removeFromFolder before. Is my file now in two places?
Possibly. Open the file in Drive, click the folder icon next to the filename at the top of the viewer, and check how many parent folders are listed. If you see more than one, the removeFromFolder call either was never executed or silently failed. You can fix it by calling moveTo(correctFolder) now — that will clear all extra parents in one call.
Can I move a folder the same way?
DriveApp.Folder does not expose a moveTo method. To reparent a folder via Apps Script you have to use the Drive advanced service (not DriveApp) and call Drive.Files.update with the addParents and removeParents query parameters. Enable the Drive advanced service in the script editor under Services, then use Drive.Files.update('FOLDER_ID', {}, {addParents: 'NEW_PARENT_ID', removeParents: 'OLD_PARENT_ID'}).
Will moveTo trigger any Drive notifications or activity log entries?
Yes. Drive's activity log records the move as a move event attributed to the account that authorized the script. Collaborators with notification preferences set on the file will receive a moved notification. There is no way to suppress Drive activity logging from Apps Script — it is server-side and outside the script's control.