My goal is to delete files from a specific folder older than 60 days.
I have a script as follows (based on code from another post I can't find anymore):
function getOldFileIDs() {
var fileIDs = [];
// Old date is 60 days
var oldDate = new Date().getTime() - 3600*1000*24*60;
var cutOffDate = Utilities.formatDate(new Date(oldDate), "GMT", "yyyy-MM-dd");
// Get folderID using the URL on google drive
var folder = DriveApp.getFolderById('XXXXX');
var files = folder.searchFiles('modifiedDate < "' cutOffDate '"');
while (files.hasNext()) {
var file = files.next();
fileIDs.push(file.getId());
Logger.log('ID: ' file.getId() ', Name: ' file.getName());
}
return fileIDs;
};
function deleteFiles() {
var fileIDs = getOldFileIDs();
fileIDs.forEach(function(fileID) {
DriveApp.getFileById(fileID).setTrashed(true);
});
};
This code works but it uses "modifiedDate" When I look in the folder, I see there are many very old files with a "modified" date of today for some reason, but the "Created" date seems correct.
Therefore, I tried changing the code to "createdDate" but that doesn't work.
I decided to actually look at the documentation: https://developers.google.com/apps-script/reference/drive/drive-app#searchFiles(String) https://developers.google.com/drive/api/guides/ref-search-terms
It seems like "modifiedDate" isn't even listed yet it seems to work.
CodePudding user response:
Delete old files:
function delOldFiles() {
const dt = new Date();
const dtv = new Date(dt.getFullYear(),dt.getMonth(),dt.getDate() - 60).valueOf();
var folder = DriveApp.getFolderById('XXXXX');
var files = folder.getFiles();
while (files.hasNext()) {
var file = files.next();
if(new Date(file.getLastUpdated()).valueOf() < dtv) {
Drive.Files.remove(file.getId());
}
}
}
CodePudding user response:
Regarding your question:
Therefore, I tried changing the code to "createdDate" but that doesn't work.
This seems to be an issue which has already been reported in this issue tracker, you can keep track of this to see any updates in the future, this is another thread related to the issue. @Cooper's answer is a good workaround to achieve what you're looking for.
CodePudding user response:
Issue and workaround:
The parameter of "searchFiles" method uses the search query for Drive API v2. When I tested
createdDate > '####-##-##'
for "searchFiles" and "Files: list" of Drive API v2, I confirmed errors likeInvalid argument: q
andInvalid query
occurred, respectively. This has already been mentioned in Lorena Gomez's answerFortunately, when Drive API v3 is used,
createdTime
can be used.createdTime
of Drive API v3 is the same withcreatedDate
of Drive API v2. In this answer, as a workaround, I would like to propose using Drive API v3 instead of Drive API v2 ("searchFiles" of DriveApp). I have already posted this workaround at this post. But, this has not been posted in Stackoverflow. When this is posted here, I thought that it might be useful for other users.
When Drive API v3 is reflected in your script, how about the following modification?
Modified script:
This script uses Drive API. So, please enable Drive API at Advanced Google services.
function getOldFileIDs() {
var folderId = "###"; // Please set your folder ID.
var fileIDs = [];
// Old date is 60 days
var oldDate = new Date().getTime() - 3600 * 1000 * 24 * 60;
var cutOffDate = Utilities.formatDate(new Date(oldDate), "GMT", "yyyy-MM-dd");
var query = `'${folderId}' in parents and createdTime < '${cutOffDate}' and trashed=false`;
var pageToken = "";
do {
var url = encodeURI(`https://www.googleapis.com/drive/v3/files?q=${query}&pageSize=1000&pageToken=${pageToken}&fields=files(id,name,createdTime),nextPageToken&orderBy=createdTime`);
var res = UrlFetchApp.fetch(url, { headers: { authorization: "Bearer " ScriptApp.getOAuthToken() } });
var obj = JSON.parse(res.getContentText());
if (obj.files.length > 0) {
fileIDs = [...fileIDs, ...obj.files.map(({ id }) => id)];
obj.files.forEach(({ id, name, createdTime }) => Logger.log(JSON.stringify({ id, name, createdTime })));
}
pageToken = obj.nextPageToken;
} while (pageToken);
return fileIDs;
}
- When this script is run, the file list including file IDs is retrieved with the search query of
'${folderId}' in parents and createdTime < '${cutOffDate}' and trashed=false
. - When you are not required to check the process, please remove
obj.files.forEach(({ id, name, createdTime }) => Logger.log(JSON.stringify({ id, name, createdTime })));
.
Note:
As additional information, in order to remove the files, when the number of files is large when setTrashed
is run in a loop, the process cost becomes high. In this case, how about using batch requests? When batch requests are used, the process cost can be reduced. Ref
When batch requests are used with Google Apps Script, a script is a bit complicated. So, I created a Google Apps Script library. Ref When your script of deleteFiles()
is modified for removing the files with the batch requests, how about the following modification?
1. Install Google Apps Script library.
Please install the Google Apps Script library. You can see how to install it here.
2. Sample script.
In this sample, the result is the same with setTrashed
. The files of fileIDs
are moved to the trash box.
function deleteFiles() {
var fileIDs = getOldFileIDs();
var requests = fileIDs.map(id => ({
method: "PATCH",
endpoint: `https://www.googleapis.com/drive/v3/files/${id}`,
requestBody: { trashed: true },
}));
var result = BatchRequest.EDo({ batchPath: "batch/drive/v3", requests });
console.log(result);
}
If you want to completely delete the files of fileIDs
, please use the following script. But, this script completely deletes the files. So, please be careful about this. So, I would like to recommend using the above script. After you check the files in the trash box, you can empty the trash box.
function deleteFiles() {
var fileIDs = getOldFileIDs();
var requests = fileIDs.map(id => ({
method: "DELETE",
endpoint: `https://www.googleapis.com/drive/v3/files/${id}`,
}));
var result = BatchRequest.EDo({ batchPath: "batch/drive/v3", requests });
console.log(result);
}