The Google Drive Cleaner Bot is a simple script powered by Google Apps Script that helps you automatically detect and clean up clutter in your Google Drive.
- Step 1: Click on the
Copy
button to copy the code snippet. - Step 2: Paste the copied code into your project’s script editor.
Apps Scripts Blog
Apps Scripts Code
function driveCleaner() {
const SIZE_LIMIT_MB = 50;
const SIZE_LIMIT_BYTES = SIZE_LIMIT_MB * 1024 * 1024;
const files = [];
const duplicatesMap = {};
let largeCount = 0;
let duplicateCount = 0;
let totalCount = 0;
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const sheet = spreadsheet.getActiveSheet();
setupReportSheet(sheet);
const driveFiles = DriveApp.getFiles();
while (driveFiles.hasNext()) {
const file = driveFiles.next();
totalCount++;
const name = file.getName();
const size = file.getSize();
const type = file.getMimeType();
const created = file.getDateCreated();
const url = file.getUrl();
const sizeMB = (size / (1024 * 1024)).toFixed(2);
let flag = "Normal";
const key = `${name}_${size}`;
const isDuplicate = duplicatesMap[key] === true;
const isLarge = size > SIZE_LIMIT_BYTES;
if (isDuplicate && isLarge) {
flag = "Large, Duplicate";
duplicateCount++;
largeCount++;
} else if (isDuplicate) {
flag = "Duplicate";
duplicateCount++;
} else if (isLarge) {
flag = "Large";
largeCount++;
}
files.push([name, sizeMB, type, created, url, flag]);
duplicatesMap[key] = true;
}
if (files.length > 0) {
sheet.getRange(2, 1, files.length, 6).setValues(files);
applyConditionalFormatting(sheet);
sheet.getRange(1, 1, sheet.getLastRow(), 6)
.setBorder(true, true, true, true, true, true);
sheet.getRange(1, 1, sheet.getLastRow(), 6)
.applyRowBanding(SpreadsheetApp.BandingTheme.LIGHT_GREY);
}
SpreadsheetApp.flush();
const reportUrl = spreadsheet.getUrl();
Logger.log("β
Report Updated: " + reportUrl);
showSummaryAlert(duplicateCount, largeCount);
showSidebar();
sendSummaryEmail(totalCount, largeCount, duplicateCount, reportUrl);
}
function setupReportSheet(sheet) {
const headers = ["π File Name", "π¦ Size (MB)", "π Type", "π
Created Date", "π URL", "π© Flag"];
sheet.clear();
sheet.setName("Drive Cleanup Report");
sheet.appendRow(headers);
const headerRange = sheet.getRange(1, 1, 1, headers.length);
headerRange.setFontWeight("bold").setBackground("#f4f4f4").setFontSize(12);
sheet.setFrozenRows(1);
sheet.autoResizeColumns(1, headers.length);
}
function applyConditionalFormatting(sheet) {
const lastRow = sheet.getLastRow();
if (lastRow < 2) return; // No data const flagRange = sheet.getRange(2, 6, lastRow - 1); const rules = [ SpreadsheetApp.newConditionalFormatRule() .whenTextEqualTo("Large") .setBackground("#ffdddd") .setRanges([flagRange]) .build(), SpreadsheetApp.newConditionalFormatRule() .whenTextEqualTo("Duplicate") .setBackground("#fff5cc") .setRanges([flagRange]) .build(), SpreadsheetApp.newConditionalFormatRule() .whenTextEqualTo("Large, Duplicate") .setBackground("#ffe0b2") .setRanges([flagRange]) .build() ]; const existingRules = sheet.getConditionalFormatRules(); sheet.setConditionalFormatRules([...existingRules, ...rules]); } function showSummaryAlert(duplicateCount, largeCount) { const ui = SpreadsheetApp.getUi(); ui.alert(`π Drive Cleanup Summary:\n\nπ Duplicate Files: ${duplicateCount}\nπ¦ Large Files: ${largeCount}`); } function showSidebar() { const html = HtmlService.createHtmlOutputFromFile("Sidebar") .setTitle("π§Ή Drive Cleaner"); SpreadsheetApp.getUi().showSidebar(html); } function sendSummaryEmail(total, largeCount, dupCount, reportLink) { const email = Session.getActiveUser().getEmail(); const subject = "π§Ή Google Drive Cleanup Summary"; const body = ` Hey ${email}, Hereβs your Drive Cleanup Summary: π Total files scanned: ${total} π¦ Large files (>50MB): ${largeCount}
π Duplicate files: ${dupCount}
π Report: ${reportLink}
Open the link above to view flagged files.
β Your Cleaner Bot π€`;
GmailApp.sendEmail(email, subject, body);
}
function onOpen() {
const ui = SpreadsheetApp.getUi();
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const flags = sheet.getRange(2, 6, sheet.getLastRow() - 1).getValues();
let duplicateCount = 0;
let largeCount = 0;
flags.forEach(row => {
const flag = row[0];
if (flag.includes("Duplicate")) duplicateCount++;
if (flag.includes("Large")) largeCount++;
});
ui.alert(`π Drive Cleanup Summary:\n\nπ Duplicate Files: ${duplicateCount}\nπ¦ Large Files: ${largeCount}`);
showSidebar();
}
function getDuplicateFiles() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const data = sheet.getDataRange().getValues();
const duplicates = [];
for (let i = 1; i < data.length; i++) { const flag = data[i][5]; if (flag.includes("Duplicate")) { duplicates.push({ name: data[i][0], url: data[i][4], rowIndex: i + 1, id: extractFileId(data[i][4]) }); } } return duplicates; } function extractFileId(url) { const match = url.match(/[-\w]{25,}/); return match ? match[0] : null; } function deleteSelectedFiles(selectedRows) { const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); let deletedCount = 0; selectedRows.sort((a, b) => b - a);
for (let i = 0; i < selectedRows.length; i++) {
const row = selectedRows[i];
const fileUrl = sheet.getRange(row, 5).getValue();
const fileId = extractFileId(fileUrl);
try {
if (fileId) {
DriveApp.getFileById(fileId).setTrashed(true);
sheet.deleteRow(row);
deletedCount++;
}
} catch (e) {
Logger.log(`β Could not delete file at row ${row}: ${e}`);
}
}
return deletedCount;
}
Sidebar Code
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<style>
body { font-family: Arial, sans-serif; padding: 10px; }
button {
background-color: #d9534f;
color: white;
border: none;
padding: 10px;
font-size: 14px;
border-radius: 4px;
cursor: pointer;
margin-top: 10px;
}
button:hover { background-color: #c9302c; }
.file-entry { margin: 6px 0; }
</style>
</head>
<body>
<h3>π Select Duplicate Files</h3>
<div id="fileList">Loading...</div>
<button onclick="deleteSelected()">Delete Selected Files</button>
<p id="status" style="color:green;"></p>
<script>
let allFiles = [];
function deleteSelected() {
const checkboxes = document.querySelectorAll("input[type='checkbox']:checked");
const selectedRows = [];
checkboxes.forEach(cb => {
selectedRows.push(parseInt(cb.dataset.row));
});
if (selectedRows.length === 0) {
document.getElementById("status").innerText = "β οΈ Please select at least one file.";
return;
}
document.getElementById("status").innerText = "Deleting...";
google.script.run.withSuccessHandler(function(count) {
document.getElementById("status").innerText = `β
Deleted ${count} file(s)`;
loadFiles();
}).deleteSelectedFiles(selectedRows);
}
function loadFiles() {
google.script.run.withSuccessHandler(function(files) {
allFiles = files;
const container = document.getElementById("fileList");
if (files.length === 0) {
container.innerHTML = "<p>No duplicate files found!</p>";
return;
}
container.innerHTML = "";
files.forEach(file => {
const div = document.createElement("div");
div.className = "file-entry";
div.innerHTML = `
<input type="checkbox" data-row="${file.rowIndex}" id="file${file.rowIndex}">
<label for="file${file.rowIndex}">${file.name}</label>
`;
container.appendChild(div);
});
}).getDuplicateFiles();
}
loadFiles();
</script>
</body>
</html>