Do not make copy of existing file in destination folder - google-apps-script

I've been trying to copy contents from one folder to another folder in google drive using google app script. With some online help and documentation of google script, I was able to copy files from one folder to other but it copies all files from source folder to destination folder on time trigger, but I want only the new files to get copied in my destination folder and skip the present files that are already same in my source and destination folder.
I tried to check files by name before copying but couldn't find a way to compare files by name in two different folders of gdrive.
function CopyFiles() {
var SourceFolder = DriveApp.getFolderById('Sid');
var SourceFiles = DriveApp.getFolderById('Sid').getFiles();
var DestFolder = DriveApp.getFolderById('Did');
var DestFiles = DriveApp.getFolderById('Did').getFiles();
while (SourceFiles.hasNext())
{
var files = SourceFiles.next();
var dfiles = DestFiles.next();
if ( files == dfiles){
file.setTrashed(true);}
else{
var f = files.makeCopy(DestFolder);
}
}
}
What I want to achieve is that Script compares files by name in destination folder and if files by that name already exist than skip else, create a copy of that new file in the destination folder.

Copies files from source to destination if destination does have the same file names
In this version no files get trashed.
function CopyFiles() {
var srcFldr=DriveApp.getFolderById('srcId');
var srcFiles=srcFldr.getFiles();
var desFldr=DriveApp.getFolderById('desId');
var desFiles=desFldr.getFiles();
var dfnA=[];
while(desFiles.hasNext()) {
var df=desFiles.next();
dfnA.push(df.getName());
}
while(srcFiles.hasNext()) {
var sf=srcFiles.next();
if(dfnA.indexOf(sf.getName())==-1) {
sf.makeCopy(sf.getName(),desFldr);
}
}
}

Related

Google Apps Script Unzipping Files - Issues

I have a script that looks in a destination folder and unzips files to a new folder. All works perfect as long as the zip contains just one file; anymore and I only seem to unzip the first file.
Im pretty sure the line that's causing this is which is picking the first record in the array of files however I am not quite skilful enough to figure out how to get around this. Any help would be greatly appreciated
[var newDriveFile = DestinationFolder.createFile(unZippedfile[0]);]
//Unzips all ZIP files in the folder
function Unzip() {
//Add folder ID to select the folder where zipped files are placed
var SourceFolder = DriveApp.getFolderById("14vRNV3FZJicplxeurycsfBHmETrUQBex")
//Add folder ID to save the where unzipped files to be placed
var DestinationFolder = DriveApp.getFolderById("1OJXkPrUqcqapsv366oCV_ZsvaECstKTn")
//Select the Zip files from source folder using the Mimetype of ZIP
var ZIPFiles = SourceFolder.getFilesByType(MimeType.ZIP)
//var ZIPFiles = SourceFolder.getFilesByName('MTTR.zip')
//Loop over all the Zip files
while (ZIPFiles.hasNext()){
// Get the blob of all the zip files one by one
var fileBlob = ZIPFiles.next().getBlob();
//Use the Utilities Class to unzip the blob
var unZippedfile = Utilities.unzip(fileBlob);
//Unzip the file and save it on destination folder
var newDriveFile = DestinationFolder.createFile(unZippedfile[0]); //I think this line is where my issue is
}
Logger.log("Finished Unzipping files")
}
As what Rodrigo mentioned in the comments, you need to loop it on all the files. unZippedfile.length is the number of files in the zip file. Use a loop around the createFile method.
Code:
// loop to all zip files
while (ZIPFiles.hasNext()){
var fileBlob = ZIPFiles.next().getBlob();
var unZippedfile = Utilities.unzip(fileBlob);
// loop to all items inside the current zip file
for (i=0; i<unZippedfile.length; i++) {
var newDriveFile = DestinationFolder.createFile(unZippedfile[i]);
}
}
Output:
Note:
Sample output above show the unzipped files on the same directory as I instantiated both source and destination with the same directory ID.

Unzip File Only If New in Google Apps Scripts

I have a folder (let's call it the source folder) on Google Drive that is updated from time to time with new zip files (underlying files are PDFs). I am trying to use Google Apps Script to unzip only the new zip files and place the underlying PDFs in another folder (let's call it the destination folder).
I am currently using the following code to unzip the files in the source folder, running on a time-based trigger. My current code does not differentiate between old and new zip files so I am getting a large number of duplicates accumulating in the destination folder. (I found this code on WeirdGeek: https://www.weirdgeek.com/2019/10/unzip-files-using-google-apps-script/)
function Unzip() {
//Add folder ID to select the folder where zipped files are placed
var SourceFolder = DriveApp.getFolderById("1KbyB2vTUfbwYdzBEyIwzTliXKjATbW8A")
//Add folder ID to save the where unzipped files to be placed
var DestinationFolder = DriveApp.getFolderById("1Z-iVlcROe5kVX8IkBlV9a98WKlvlfp3U")
//Select the Zip files from source folder using the Mimetype of ZIP
var ZIPFiles = SourceFolder.getFilesByType(MimeType.ZIP)
//Loop over all the Zip files
while (ZIPFiles.hasNext()){
// Get the blob of all the zip files one by one
var fileBlob = ZIPFiles.next().getBlob();
//Use the Utilities Class to unzip the blob
var unZippedfile = Utilities.unzip(fileBlob);
//Unzip the file and save it on destination folder
var newDriveFile = DestinationFolder.createFile(unZippedfile[0]);
}
}
I initially thought to add some sort of time-based restriction to the function, but because the source folder is being synced (using MultCloud) with an sFTP site, I don't want to go that direction.
I ALSO found the following code is used to put a "replace" restriction on saving new spreadsheets but couldn't figure out how to integrate this with my code. (Code is from user Tainake)
function saveAsSpreadsheet() {
var folderId = "0B8xnkPYxGFbUMktOWm14TVA3Yjg";
var folder = DriveApp.getFolderById(folderId);
var files = folder.getFilesByName(getFilename());
if (files.hasNext()) {
files.next().setTrashed(true);
}
var sheet = SpreadsheetApp.getActiveSpreadsheet();
DriveApp.getFileById(sheet.getId()).makeCopy(getFilename(), folder);
}
Any ideas on how to solve this problem would be appreciated! I am a complete noob so I apologize in advance if this is a stupid question.
EDIT: I could not figure out how to unzip only "new" files in the source folder, and so my new code moves to trash all files in the destination folder, and then unzips all files in the source folder. Code is below:
function Unzip() {
//Add folder ID to select the folder where zipped files are placed
var SourceFolder = DriveApp.getFolderById("1KbyB2vTUfbwYdzBEyIwzTliXKjATbW8A")
//Add folder ID to save the where unzipped files to be placed
var DestinationFolder = DriveApp.getFolderById("1Z-iVlcROe5kVX8IkBlV9a98WKlvlfp3U")
//Delete files from the destination folder
//Get the files in the destination folder
var files = DestinationFolder.getFiles();
//Loop through the files in the destination folder
while(files.hasNext()){
//Get the individual file in the destination folder to process
var file = files.next();
//Trash that file
file.setTrashed(true);
}
//Select the Zip files from source folder using the Mimetype of ZIP
var ZIPFiles = SourceFolder.getFilesByType(MimeType.ZIP)
//Loop over all the Zip files
while (ZIPFiles.hasNext()){
// Get the blob of all the zip files one by one
var fileBlob = ZIPFiles.next().getBlob();
//Use the Utilities Class to unzip the blob
var unZippedfile = Utilities.unzip(fileBlob);
//Unzip the file and save it on destination folder
var newDriveFile = DestinationFolder.createFile(unZippedfile[0]);
}
}
I could see how this may not be the best solution to this issue, but this allows me to have a MultCloud sync the zip files into my Google Drive, and then allows me to have those files unzipped with a function that runs from time to time. Anyone have a better idea how to accomplish the same thing without deleteing and recreating all the files every time?
EDIT 2:
Thank you to Cameron, this question is answered. I am pasting the full code I am using below, for posterity / other newbies so that they don't have to piece it together:
function Unzip() {
//Add folder ID to select the folder where zipped files are placed
var SourceFolder = DriveApp.getFolderById("1KbyB2vTUfbwYdzBEyIwzTliXKjATbW8A")
//Add folder ID to save the where unzipped files to be placed
var DestinationFolder = DriveApp.getFolderById("1Z-iVlcROe5kVX8IkBlV9a98WKlvlfp3U")
//Select the Zip files from source folder using the Mimetype of ZIP
var ZIPFiles = SourceFolder.getFilesByType(MimeType.ZIP);
var now = new Date(); //get current time after you fetch the file list from Drive.
//Get script properties and check for stored "last_execution_time"
var properties = PropertiesService.getScriptProperties();
var cutoff_datetime = properties.getProperty('last_execution_time');
//if we have last execution date, stored as a string, convert it to a Date object.
if(cutoff_datetime)
cutoff_datetime = new Date(cutoff_datetime);
//Loop over all the Zip files
while (ZIPFiles.hasNext()){
var file = ZIPFiles.next();
//if no stored last execution, or file is newer than last execution, process the file.
if(!cutoff_datetime || file.getDateCreated() > cutoff_datetime){
var fileBlob = file.getBlob();
//Use the Utilities Class to unzip the blob
var unZippedfile = Utilities.unzip(fileBlob);
//Unzip the file and save it on destination folder
var newDriveFile = DestinationFolder.createFile(unZippedfile[0]);
}
}
//store "now" as last execution time as a string, to be referenced on next run.
properties.setProperty('last_execution_time',now.toString());
}
You can use the getDateCreated() function on a File object to determine when the file was created. By checking this value against a time limit, you should be able to determine if the file is new. If you are triggering your script with at least a few hours between executions, you could use a hardcoded cutoff time. So if you are triggering your script every six hours, you could ignore any files not created within the last 6 hours, for example.
However, a more robust approach would be to store the last successful execution time in a Script Property, so you could always process any files created since the last successful execution.
Note that this code will process all files currently in the folder the first time it runs, after that it will only process files created since the last run.
var ZIPFiles = SourceFolder.getFilesByType(MimeType.ZIP);
var now = new Date(); //get current time after you fetch the file list from Drive.
//Get script properties and check for stored "last_execution_time"
var properties = PropertiesService.getScriptProperties();
var cutoff_datetime = properties.getProperty('last_execution_time');
//if we have last execution date, stored as a string, convert it to a Date object.
if(cutoff_datetime)
cutoff_datetime = new Date(cutoff_datetime);
//Loop over all the Zip files
while (ZIPFiles.hasNext()){
var file = ZIPFiles.next();
//if no stored last execution, or file is newer than last execution, process the file.
if(!cutoff_datetime || file.getDateCreated() > cutoff_datetime){
var fileBlob = file.getBlob();
//Use the Utilities Class to unzip the blob
var unZippedfile = Utilities.unzip(fileBlob);
//Unzip the file and save it on destination folder
var newDriveFile = DestinationFolder.createFile(unZippedfile[0]);
}
}
//store "now" as last execution time as a string, to be referenced on next run.
properties.setProperty('last_execution_time',now.toString());

How to Compare Destination Folders names with specific Single Source folder name?

Presently, I've been trying to copy the files or folder with files from the source lastcreated folder into the destination folder by comparing the foldername on the basis of the last date created folder. Now I want to compare the source's last date created folder by name with all destination folders, if folder by same name exits than copy the data else create a new folder by same sourcefoldername and copy the contents.
By the help of StackOverflow community, I'm able to compare folder's on basis of last date created and copy the contents but now I want to compare the source last date created foldername with the destination's all folder. If folder by same exits than copy the data in it else it creates a new folder. Attached is the code for getting last date created folder and comparinng with destination folder.
var destSubFolders = destLastFolder.getFolders();
var destSubArray=[];
while(destSubFolders.hasNext()) {
var destSubfolder = destSubFolders.next();
destSubArray.push({
value: destSubfolder.getDateCreated().valueOf(),
sourceFolderId: destSubfolder.getId()
});
}
destSubArray.sort(function(a,b){return b.value-a.value;}); // Comparing between the date created and extracts the last created folder.
var destLastSubFolder=DriveApp.getFolderById(destSubArray[0].sourceFolderId);// gets the last created sub folder by id.
var destinationLastSubFolderFiles= destLastSubFolder.getFiles();//get files of the last created subfolder.
var d_SubName = destLastSubFolder.getName(); // get name of the last created subfolder.
if(s_SubName == d_SubName ) { //condition for comapring source and destination last created subfolder names.
var dfnA=[]; // getting files from source sub folder and copying into destination folder.
while(destinationLastSubFolderFiles.hasNext()) {
var dF=destinationLastSubFolderFiles.next();
dfnA.push(dF.getName());
}
while(sourceLastSubFolderFiles.hasNext()) {
var sF=sourceLastSubFolderFiles.next();
if(dfnA.indexOf(sF.getName())==-1) {
sF.makeCopy(sF.getName(),destLastSubFolder); // copying files after comparing by names.
}
}
} else { //creates new folder by source subfolder name and copies data into new created folder.
var sNewName = lastSubFolder.getName();
var dFolderName=destLastFolder.createFolder(sNewName);
while(sourceLastSubFolderFiles.hasNext()) {
var sFilesIterator=sourceLastSubFolderFiles.next();
sFilesIterator.makeCopy(sFilesIterator.getName(),dFolderName); // copying files after comparing by names.
}
}
I need a comparison of source folder name with destination all folder names and if matches then only copy the contents else create a new folder and contents.
This works for me:
function findSubFolderWithLastDate(startingFolderId) {
var startingFolderId=startingFolderId||'defaultId';
var startFolder=DriveApp.getFolderById(startingFolderId);
var srcFldrs=startFolder.getFolders();
var fldrA=[];
while(srcFldrs.hasNext()) {
var srcFldr=srcFldrs.next();
fldrA.push({value:srcFldr.getLastUpdated().valueOf(),id:srcFldr.getId(),name:srcFldr.getName()})
}
return fldrA.sort(function(a,b){return(b.value-a.value);})[0].id;
}
function copyingFilesFromSourceToDestinationFolderWithSameName(srcfldrId,desfldrId) {
var desFldr=DriveApp.getFolderById(desfldrId);
var srcFldr=DriveApp.getFolderById(srcfldrId);
var srcSubFldrs=srcFldr.getFolders();
while(srcSubFldrs.hasNext()) {
var srcSubFldrFound=false;
var srcSubFldr=srcSubFldrs.next();
var desSubFldrs=desFldr.getFolders();
while(desSubFldrs.hasNext()) {
var desSubFldr=desSubFldrs.next();
if(desSubFldr.getName()==srcSubFldr.getName()) {
srcSubFldrFound=true;
var files=srcSubFldr.getFiles();
while(files.hasNext()) {
var file=files.next();
file.makeCopy(file.getName(),desSubFldr);
}
break;
}
}
if(!srcSubFldrFound) {
var newFldr=desFldr.createFolder(srcSubFldr.getName());
var files=srcSubFldr.getFiles();
while(files.hasNext()) {
var file=files.next();
file.makeCopy(file.getName(),newFldr)
}
}
}
}

Google Spredsheet - Copy files to another folder in TeamDrive

I try to copy some movies from a Google Drive folder to another Folder and rename the file by using a script in a Spreadsheet. (other options than spreadsheets are also welcome, but this seems to be easyest). I got access on both folders.
a) is working as it should, makeing a copy of the file in the same folder;
b) is also doing a copy but still in the same folder and not in the destination-folder;
c) giving error:
"cannot find method makeCopy(string,string)"
function copyFile() {
var FileToCopy=DriveApp.getFileById('12B-zfprxgazbZ4JFxyrqhYveofYATzC1');
FileToCopy.makeCopy()
}
function copyFile() {
var FileToCopy=DriveApp.getFileById('12B-zfprxgazbZ4JFxyrqhYveofYATzC1');
var Destination = "1yC_nDk9VQLHBAkYNwNkRucfxp6yFBIV1";
FileToCopy.makeCopy(Destination)
}
function copyFile() {
var FileToCopy=DriveApp.getFileById('12B-zfprxgazbZ4JFxyrqhYveofYATzC1');
var Destination = "1yC_nDk9VQLHBAkYNwNkRucfxp6yFBIV1";
var Filename = "newFile.mp4";
FileToCopy.makeCopy(Filename, Destination)
}
Instead of
var Destination = "1yC_nDk9VQLHBAkYNwNkRucfxp6yFBIV1";
try
var Destination = DriveApp.getFolderById("1yC_nDk9VQLHBAkYNwNkRucfxp6yFBIV1");
If you see the documentation, you need to pass the folder and not the ID of the destination folder.

Download Folder as Zip Google Drive API

I currently have a Google App Script in Google Sheet that gives me the URL of a folder, which I can then use to download. Though it is an extra step I would like to remove, and get the URL of the zipped content directly.
Here's my code (google app script):
function downloadSelectedScripts() {
// ...
var scriptFiles = getScriptFiles(scriptFileNames)
var tempFolder = copyFilesToTempFolder(scriptFiles)
Browser.msgBox(tempFolder.getUrl())
}
function copyFilesToTempFolder(files) {
var tempFolder = DriveApp.getFolderById(FOLDERS.TEMP)
var tempSubFolder = tempFolder.createFolder('download_' + Date.now())
for (var i in files) {
var file = files[i]
file.makeCopy(file.getName(), tempSubFolder)
}
return tempSubFolder
}
You want to compress all files in a folder as a zip file.
The folder has no subfolders.
All files are only text files.
The total size of all files is less than 50 MB.
You want to retrieve the URL for downloading the zip file.
If my understanding is correct, how about this sample script? The flow of this script is as follows.
Retrieve folder.
Retrieve blobs of all files in the folder.
Compress blobs and retrieve a blob of zip.
Create a zip blob as a file.
Retrieve URL for downloading.
Sample script:
When you use this script, please set the folder ID of folder that you want to compress.
function myFunction() {
var folderId = "###"; // Please set the folder ID here.
var folder = DriveApp.getFolderById(folderId);
var files = folder.getFiles();
var blobs = [];
while (files.hasNext()) {
blobs.push(files.next().getBlob());
}
var zipBlob = Utilities.zip(blobs, folder.getName() + ".zip");
var fileId = DriveApp.createFile(zipBlob).getId();
var url = "https://drive.google.com/uc?export=download&id=" + fileId;
Logger.log(url);
}
Result:
The direct link of the zip file is returned as follows.
https://drive.google.com/uc?export=download&id=###
Note:
In the current stage, unfortunately, the folders cannot be included in the zip data with Google Apps Script.
In this sample script, the filename of zip file is the folder name. So please modify it for your situation.
If you want to download the zip file without login to Google, please share the file.
Reference:
zip(blobs, name)