0

I want to look for folders (let's call each of them $folder) containing node_modules/ folder.

node_modules folders are places to install javascript libraries, and these libraries themselves often have folders with node_modules, so it behooves us to always exclude node_modules and its children from the above search. They can also safely be excluded from the below:

For each $folder, find their most recently modified file. If that date is more than let's say 4 weeks old, I'd like to delete $folder/node_modules.

I imagine I can add this to cron... but Im not sure if apple provides a nicer way to do this than via bash or node or whatever

2 Answers 2

1

Here is the general version - a function that removes all subdirectories of @root named @target. Use with caution.

https://raw.githubusercontent.com/angstyloop/nodejs-utils/main/rmDirRecursive.js

#! /usr/bin/env node

const { rmSync } = require('fs');
const { join, posix: { basename } } = require('path');
const listDirs = require('./listDirs');

/* Starting in the directory named @root, recursively find and remove all
 * all directories named @target. Implements BFS with a FIFO queue.
 *
 * @root - Full or relative path of directory to start in.
 * @target - name (basename, not path) of target directory to remove.
 *
 */
module.exports = function rmDirRecursive(root, target) {
    let dir = root;
    const dirs = listDirs(dir);
    while (dirs.length) {
        dir = dirs.shift();
        if (basename(dir) === target) {
            rmSync(dir, { recursive: true, force: true });
        } else {
            dirs.push(...listDirs(dir));
        }
    }
}

I'll write async version if anyone wants, just email me.

2
  • 1
    Link-only answers are not helpful should the link gets broken. It is better to include as much detail as possible in an answer.
    – Alper
    Oct 2, 2022 at 11:19
  • Hey good point thanks buddy - updated
    – angstyloop
    Mar 30, 2023 at 7:19
0

I should have had some patience.. instead of posting the question here first. I think I have a solution.

~/bin/clean_old_projects.js

const { readdirSync, statSync, rmSync } = require('node:fs')
const {execSync} = require('node:child_process')

const getDirectories = source => {  
  try {
    return readdirSync(source, { withFileTypes: true })
      .filter(dirent => dirent.isDirectory())
      .map(dirent => `${source}/${dirent.name}`)
  }
  catch (e) { return [] }
}

targets = [process.env.HOME]
nodeProjects = []
for (let target of targets) {
  if (/node_modules$/.test(target)) {
    nodeProjects.push(target.replace('/node_modules', ''))
  } else {
    targets.push(...getDirectories(target))
  }
}

const sh = fh => `find "${fh}" -name node_modules -prune -o -type f -print0 | xargs -0 stat -f "%m %N" | sort -rn | head -1 | cut -f2- -d" "`

const fourWeeks = 2419200
const now = new Date()
for (let target of nodeProjects) {
  const fh = execSync(sh(target)).toString().trim()
  if(now - statSync(fh.length? fh: target).mtime > fourWeeks)
    rmSync(target + '/node_modules',  { recursive: true, force: true })
}

then crontab -e and save:

0 3 14,28 * * /usr/local/bin/node /Users/MY_HOME_DIRECTORY/bin/clean_old_projects.js

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .