-
-
Save ruisilva450/9ecac5e0a8c7609b92fd3c15739a200a to your computer and use it in GitHub Desktop.
Faster `rm -rf node_modules`
This file contains hidden or 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
| #!/bin/bash | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m' | |
| CYAN='\033[0;36m' | |
| NC='\033[0m' | |
| # Find project root (directory containing package.json or node_modules) | |
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| PROJECT_ROOT="$SCRIPT_DIR" | |
| while [ "$PROJECT_ROOT" != "/" ]; do | |
| if [ -f "$PROJECT_ROOT/package.json" ] || [ -d "$PROJECT_ROOT/node_modules" ]; then | |
| break | |
| fi | |
| PROJECT_ROOT="$(dirname "$PROJECT_ROOT")" | |
| done | |
| cd "$PROJECT_ROOT" || exit 1 | |
| if [ ! -d "node_modules" ]; then | |
| echo -e "${YELLOW}⚠️ node_modules directory not found in project root: ${PROJECT_ROOT}${NC}" | |
| exit 0 | |
| fi | |
| TOTAL=$(find node_modules -mindepth 1 -maxdepth 1 2>/dev/null | wc -l | tr -d ' ') | |
| if [ "$TOTAL" -eq 0 ]; then | |
| echo -e "${YELLOW}⚠️ node_modules directory is empty!${NC}" | |
| exit 0 | |
| fi | |
| # Determine number of parallel processes (use CPU cores or max 8) | |
| if command -v sysctl >/dev/null 2>&1; then | |
| CPU_CORES=$(sysctl -n hw.ncpu 2>/dev/null || echo "4") | |
| else | |
| CPU_CORES=4 | |
| fi | |
| PARALLEL=$((CPU_CORES > 8 ? 8 : CPU_CORES)) | |
| PARALLEL=$((PARALLEL < 2 ? 2 : PARALLEL)) | |
| show_progress() { | |
| local current=$1 | |
| local total=$2 | |
| local percent=$((current * 100 / total)) | |
| local bar_length=50 | |
| local filled=$((current * bar_length / total)) | |
| local bar="" | |
| for ((i=0; i<filled; i++)); do | |
| bar="${bar}█" | |
| done | |
| for ((i=filled; i<bar_length; i++)); do | |
| bar="${bar}░" | |
| done | |
| printf "\r${CYAN}[${bar}] ${percent}%% (${current}/${total})${NC}" | |
| } | |
| ITEMS_PER_PART=$((TOTAL / PARALLEL)) | |
| ITEMS_PER_PART=$((ITEMS_PER_PART < 1 ? 1 : ITEMS_PER_PART)) | |
| TEMP_DIR=$(mktemp -d) | |
| trap "rm -rf $TEMP_DIR" EXIT | |
| PART_NUM=0 | |
| CURRENT_ITEM=0 | |
| while IFS= read -r item; do | |
| if [ $((CURRENT_ITEM % ITEMS_PER_PART)) -eq 0 ] && [ $CURRENT_ITEM -gt 0 ]; then | |
| PART_NUM=$((PART_NUM + 1)) | |
| fi | |
| echo "$item" >> "$TEMP_DIR/part_$PART_NUM" | |
| CURRENT_ITEM=$((CURRENT_ITEM + 1)) | |
| done < <(find node_modules -mindepth 1 -maxdepth 1) | |
| # Spawn parallel deletion processes for each partition | |
| PIDS=() | |
| for part_file in "$TEMP_DIR"/part_*; do | |
| [ -f "$part_file" ] || continue | |
| ( | |
| while IFS= read -r item; do | |
| rm -rf "$item" 2>/dev/null | |
| done < "$part_file" | |
| ) & | |
| PIDS+=($!) | |
| done | |
| while [ ${#PIDS[@]} -gt 0 ]; do | |
| NEW_PIDS=() | |
| for pid in "${PIDS[@]}"; do | |
| if kill -0 $pid 2>/dev/null; then | |
| NEW_PIDS+=($pid) | |
| fi | |
| done | |
| PIDS=("${NEW_PIDS[@]}") | |
| REMAINING=$(find node_modules -mindepth 1 -maxdepth 1 2>/dev/null | wc -l | tr -d ' ') | |
| DELETED=$((TOTAL - REMAINING)) | |
| show_progress $DELETED $TOTAL | |
| [ ${#PIDS[@]} -eq 0 ] && break | |
| # Small sleep to avoid excessive CPU usage | |
| sleep 0.05 | |
| done | |
| for pid in "${PIDS[@]}"; do | |
| wait $pid 2>/dev/null | |
| done | |
| if [ -d "node_modules" ]; then | |
| rm -rf node_modules 2>/dev/null | |
| fi | |
| show_progress $TOTAL $TOTAL | |
| printf "\r${NC}\n" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment