Last active
October 16, 2023 18:53
-
-
Save parmindersk/f89c8a222af8c45951ca013dcca51138 to your computer and use it in GitHub Desktop.
Script to create a list of exclusions for time machine. Edit the config section at the top of the file. Running it will create a shell file that can be run to add time machine exclusions on a Mac. Please review the generated file before running to make sure it includes what you intended for it to have
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// --Config section-- | |
// SHELL file that will be created with tmutil addexclusion | |
const EXCLUSION_SHELL = "tmExceptionAdder.sh"; | |
// Paths in the user directory that will be directly added to exclusions | |
const userPathsToIgnore = ["Library", ".vscode", ".npm", ".nvm", ".gradle", ".expo", ".kube"]; | |
// Paths to scan under the user directory ( | |
const userPathsToScan = [""]; | |
// Folders to search for in the scanned paths | |
const toSearch = ["node_modules", "WEB-INF/lib"]; | |
// Absolute paths to add to exclusions | |
const absolutePathsToIgnore = []; | |
// Absolute paths to add to exclusions | |
const absolutePathsToScan = []; | |
// --Config section end-- | |
const user = require("os"); | |
const fs = require("fs"); | |
const startingDir = user.homedir(); | |
const homeDir = startingDir.endsWith("/") ? startingDir : `${startingDir}/`; | |
let pathsToScan = userPathsToScan.map((upi) => `${homeDir}${upi}`); | |
pathsToScan.push(...absolutePathsToScan); | |
pathsToScan = [...new Set(pathsToScan)]; | |
pathsToScan.sort(); | |
// Deduplicate by parent | |
let root = pathsToScan[0]; | |
for (let i = 1; i < pathsToScan.length; ) { | |
if (pathsToScan[i].startsWith(root)) { | |
pathsToScan.splice(i, 1); | |
} else { | |
root = pathsToScan[i]; | |
i++; | |
} | |
} | |
console.log("The following paths will be scanned: ", pathsToScan); | |
const getPaths = (root, search, ignoreList) => { | |
// console.log("Scanning %s", root); | |
const paths = []; | |
if (ignoreList.indexOf(root) > -1) { | |
return paths; | |
} | |
if (!fs.existsSync(root) || fs.lstatSync(root).isSymbolicLink()) { | |
return paths; | |
} | |
if (root.indexOf(`/${search}`) > -1) { | |
return [root]; | |
} else { | |
if ( | |
!fs.lstatSync(root).isSymbolicLink() && | |
fs.statSync(root).isDirectory() | |
) { | |
let children; | |
try { | |
fs.accessSync(root, fs.constants.R_OK); | |
children = fs.readdirSync(root); | |
} catch (err) { | |
console.log("%s is not readable", root); | |
return paths; | |
} | |
for (let child of children) { | |
const path = root.endsWith("/") | |
? `${root}${child}` | |
: `${root}/${child}`; | |
if ( | |
!fs.lstatSync(path).isSymbolicLink() && | |
fs.statSync(path).isDirectory() | |
) { | |
paths.push(...getPaths(path, search, ignoreList)); | |
} | |
} | |
} | |
} | |
return paths; | |
}; | |
const getPathsAsync = async (root, search, ignoreList) => { | |
console.log("Scanning %s for %s", root, search); | |
const task = new Promise((resolve) => { | |
setTimeout(() => { | |
const paths = getPaths(root, search, ignoreList); | |
resolve(paths); | |
}); | |
}); | |
return task; | |
}; | |
let ignoredPaths = userPathsToIgnore.map((upi) => `${homeDir}${upi}`); | |
ignoredPaths.push(...absolutePathsToIgnore); | |
console.log("Paths that will be added to exclusions", ignoredPaths); | |
let paths = [...ignoredPaths]; | |
const tasks = []; | |
pathsToScan.forEach((path) => { | |
toSearch.forEach((search) => { | |
tasks.push(getPathsAsync(path, search, ignoredPaths)); | |
}); | |
}); | |
(async function () { | |
const values = await Promise.all(tasks); | |
values.forEach((value) => paths.push(...value)); | |
fs.writeFileSync( | |
EXCLUSION_SHELL, | |
paths | |
.map((path) => | |
/\s/.test(path) | |
? `tmutil addexclusion "${path}"` | |
: `tmutil addexclusion ${path}` | |
) | |
.join("\n") | |
); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment