Google apps scripts
We used this code:
// === CONFIGURATION ===
// The exact phrase to search for within the content of your Google Drive files.
const SEARCH_QUERY = 'fullText contains "Knowledge Aura"';
// The name of the folder where matching files will be copied.
// If this folder doesn't exist in the root of your Drive, it will be created.
const TARGET_FOLDER_NAME = "Classification";
// === END CONFIGURATION ===
/**
* Main function to be executed.
* This function finds documents containing the SEARCH_QUERY and copies them
* to the TARGET_FOLDER_NAME.
*/
function copyFilesWithKeyword() {
try {
// 1. Get or create the target folder
const targetFolder = getOrCreateFolder_(TARGET_FOLDER_NAME);
if (!targetFolder) {
const errorMessage = `Failed to get or create the target folder: "${TARGET_FOLDER_NAME}". Script cannot continue. Check logs for details.`;
Logger.log(errorMessage);
Browser.msgBox("Error", errorMessage, Browser.Buttons.OK);
return;
}
Logger.log(`Using target folder: "${TARGET_FOLDER_NAME}" (ID: ${targetFolder.getId()})`);
// 2. Search for files containing the keyword
Logger.log(`Searching for files with query: ${SEARCH_QUERY}`);
const files = DriveApp.searchFiles(SEARCH_QUERY);
let filesFoundCount = 0;
let filesCopiedCount = 0;
let filesSkippedCount = 0; // Count files that are already the script's own output (e.g. the script file itself if named with keyword)
if (!files.hasNext()) {
Logger.log(`No files found matching the query: "${SEARCH_QUERY}".`);
Browser.msgBox("Information", `No files found containing the phrase "${SEARCH_QUERY}".`, Browser.Buttons.OK);
return;
}
// 3. Iterate through found files and copy them
while (files.hasNext()) {
const file = files.next();
filesFoundCount++;
Logger.log(`Processing file ${filesFoundCount}: "${file.getName()}" (ID: ${file.getId()}, Owner: ${file.getOwner() ? file.getOwner().getEmail() : 'N/A'})`);
// Avoid copying the script file itself if it happens to contain the keyword and is in the search results.
// Also avoid copying files that are already in the target folder (simplistic check, assumes it's not the source)
if (ScriptApp.getScriptId() === file.getId()) {
Logger.log(`Skipping copy of the script file itself: "${file.getName()}"`);
filesSkippedCount++;
continue;
}
// Check if the file's parent is already the target folder.
// This is a simple check to avoid re-copying if the source file is ALREADY in the target folder.
// Note: makeCopy always creates a NEW file, so this doesn't prevent duplicate *copies* if run multiple times on same source.
let isAlreadyInTarget = false;
const parents = file.getParents();
while(parents.hasNext()){
if(parents.next().getId() === targetFolder.getId()){
isAlreadyInTarget = true;
break;
}
}
if(isAlreadyInTarget){
Logger.log(`File "${file.getName()}" is already in the target folder "${TARGET_FOLDER_NAME}". Skipping copy.`);
// If you want to create a new copy even if an original is in the target folder, remove this check.
// For now, we assume if the original is there, we don't need another copy from itself.
// filesSkippedCount++; // Or handle as per desired logic
// continue;
}
try {
// Create a copy. Drive handles duplicate names in the target folder by appending (1), (2), etc.
// We can also prefix the name.
const newFileName = file.getName(); // Using original name. Or: `Copy of ${file.getName()}`
const copiedFile = file.makeCopy(newFileName, targetFolder);
Logger.log(`Successfully copied "${file.getName()}" to "${TARGET_FOLDER_NAME}" as "${copiedFile.getName()}" (New ID: ${copiedFile.getId()}).`);
filesCopiedCount++;
} catch (e) {
Logger.log(`Error copying file "${file.getName()}": ${e.toString()}. This could be due to permissions or file type restrictions.`);
}
}
// 4. Log summary and show a message to the user
const summaryMessage = `Script finished.
Found: ${filesFoundCount} file(s).
Copied: ${filesCopiedCount} file(s).
Skipped: ${filesSkippedCount} file(s) (e.g., script file itself).
Files were copied to the folder: "${TARGET_FOLDER_NAME}".
Please check the logs for detailed information (View > Logs).`;
Logger.log(summaryMessage);
Browser.msgBox("Process Complete", summaryMessage, Browser.Buttons.OK);
} catch (error) {
Logger.log(`An unexpected error occurred in copyFilesWithKeyword: ${error.toString()} \nStack: ${error.stack}`);
Browser.msgBox("Error", `An unexpected error occurred. Please check the logs for more details. Error: ${error.message}`, Browser.Buttons.OK);
}
}
/**
* Gets a Google Drive folder by its name. If it doesn't exist in the root, it creates it.
* @param {string} folderName The name of the folder.
* @return {GoogleAppsScript.Drive.Folder|null} The Folder object, or null if an error occurs.
* @private
*/
function getOrCreateFolder_(folderName) {
try {
const folders = DriveApp.getFoldersByName(folderName);
if (folders.hasNext()) {
const folder = folders.next();
Logger.log(`Folder "${folderName}" already exists with ID: ${folder.getId()}`);
if (folders.hasNext()) {
// This means multiple folders with the same name exist at the root or where DriveApp.getFoldersByName searches.
// The script will use the first one found.
Logger.log(`Warning: Multiple folders found with the name "${folderName}". Using the first one encountered.`);
}
return folder;
} else {
Logger.log(`Folder "${folderName}" not found at the root of your Drive. Creating it...`);
const newFolder = DriveApp.createFolder(folderName);
Logger.log(`Folder "${folderName}" created successfully with ID: ${newFolder.getId()}`);
return newFolder;
}
} catch (e) {
Logger.log(`Error in getOrCreateFolder_ for folder "${folderName}": ${e.toString()}`);
// Browser.msgBox is avoided here to prevent issues if this function is called in a non-UI context later,
// the main function will handle user notification.
return null;
}
}
/**
* Adds a custom menu to the Google Sheet/Doc UI to run the script easily.
* This function runs automatically when the file (Sheet/Doc) is opened.
*/
function onOpen() {
// Use SpreadsheetApp.getUi() if script is bound to a Google Sheet
// Use DocumentApp.getUi() if script is bound to a Google Doc
// Use FormApp.getUi() if script is bound to a Google Form
// For a standalone script, this menu won't appear unless you open it via a container.
try {
const ui = SpreadsheetApp.getUi(); // Assuming it's often used with Sheets
ui.createMenu('Drive Utilities')
.addItem('Copy "Knowledge Aura" Files', 'copyFilesWithKeyword')
.addToUi();
} catch (e) {
// If not in a Spreadsheet, try DocumentApp. This is a common fallback.
try {
const ui = DocumentApp.getUi();
ui.createMenu('Drive Utilities')
.addItem('Copy "Knowledge Aura" Files', 'copyFilesWithKeyword')
.addToUi();
} catch (e2) {
Logger.log("Could not create UI menu. This script might be standalone or in an unsupported environment for onOpen() UI creation: " + e2.message);
}
}
}