Created
August 18, 2025 08:01
-
-
Save javimosch/01a457daa46bcb2c665a54728de5fd4f to your computer and use it in GitHub Desktop.
Free Up Gigabytes of Disk Space by Pruning Your 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 | |
| # Set default values | |
| dry_run=false | |
| force=false | |
| days=30 | |
| ignore_folders=(".nvm" ".vscode" ".cursor" ".pyenv" ".npm" "/windsurf" ".config" ".local") | |
| # Function to display help message | |
| usage() { | |
| echo "Usage: $0 [options]" | |
| echo "Options:" | |
| echo " --dry-run Print the node_modules folders that would be deleted without actually deleting them." | |
| echo " --force Delete node_modules folders without asking for confirmation." | |
| echo " --days <days> Set the number of days of inactivity to consider a node_modules folder for pruning (default: 30)." | |
| echo " -h, --help Display this help message." | |
| } | |
| # Parse command-line options | |
| while [[ "$#" -gt 0 ]]; do | |
| case $1 in | |
| --dry-run) dry_run=true; shift ;; | |
| --force) force=true; shift ;; | |
| --days) days="$2"; shift 2 ;; | |
| -h|--help) usage; exit 0 ;; | |
| *) echo "Unknown option: $1"; usage; exit 1 ;; | |
| esac | |
| done | |
| # Function to calculate folder size | |
| get_folder_size() { | |
| du -sh "$1" | awk '{print $1}' | |
| } | |
| # Main script logic | |
| all_node_modules_dirs=() | |
| folders_to_delete=() | |
| total_combined_size=0 | |
| ignored_paths=() | |
| find_command="find . -name node_modules -type d -prune" | |
| for folder in "${ignore_folders[@]}"; do | |
| find_command+=" -o -path './$folder' -prune" | |
| ignored_paths+=("./$folder") | |
| done | |
| # Ignore all other dotfiles | |
| find_command+=" -o -path './.*' -prune" | |
| while read -r node_modules_dir; do | |
| all_node_modules_dirs+=("$node_modules_dir") | |
| done < <(eval $find_command) | |
| if [ ${#all_node_modules_dirs[@]} -eq 0 ]; then | |
| echo "No node_modules folders found." | |
| exit 0 | |
| fi | |
| # Find the index of the most recently modified folder | |
| latest_index=-1 | |
| latest_time=0 | |
| for i in "${!all_node_modules_dirs[@]}"; do | |
| parent_dir=$(dirname "${all_node_modules_dirs[$i]}") | |
| last_modified=$(stat -c %Y "$parent_dir") | |
| if (( last_modified > latest_time )); then | |
| latest_time=$last_modified | |
| latest_index=$i | |
| fi | |
| done | |
| for i in "${!all_node_modules_dirs[@]}"; do | |
| if (( i == latest_index )); then | |
| echo "Skipping most recently modified: ${all_node_modules_dirs[$i]}" | |
| continue | |
| fi | |
| node_modules_dir=${all_node_modules_dirs[$i]} | |
| parent_dir=$(dirname "$node_modules_dir") | |
| last_modified=$(stat -c %Y "$parent_dir") | |
| current_time=$(date +%s) | |
| days_since_modified=$(( (current_time - last_modified) / 86400 )) | |
| if (( days_since_modified >= days )); then | |
| size=$(get_folder_size "$node_modules_dir") | |
| echo "Found node_modules in $parent_dir with size: $size (last modified $days_since_modified days ago)" | |
| folders_to_delete+=("$node_modules_dir") | |
| total_size_bytes=$(du -sB1 "$node_modules_dir" | awk '{print $1}') | |
| total_combined_size=$((total_combined_size + total_size_bytes)) | |
| fi | |
| done | |
| if [ ${#folders_to_delete[@]} -eq 0 ]; then | |
| echo "No node_modules folders to prune." | |
| exit 0 | |
| fi | |
| echo "Total disk usage of node_modules folders to be pruned: $(numfmt --to=iec --format="%.1f" $total_combined_size)" | |
| if [ "$dry_run" = true ]; then | |
| echo "Dry run enabled. The following node_modules folders would be deleted:" | |
| for folder in "${folders_to_delete[@]}"; do | |
| echo "- $folder" | |
| done | |
| echo "" | |
| echo "Ignored folders:" | |
| for folder in "${ignored_paths[@]}"; do | |
| echo "- $folder" | |
| done | |
| exit 0 | |
| fi | |
| if [ "$force" = false ]; then | |
| echo "The following node_modules folders will be deleted:" | |
| for folder in "${folders_to_delete[@]}"; do | |
| echo "- $folder" | |
| done | |
| read -p "Do you want to delete these folders? (y/N): " confirm | |
| if [[ ! "$confirm" =~ ^[yY]$ ]]; then | |
| echo "Deletion cancelled." | |
| exit 0 | |
| fi | |
| fi | |
| for folder in "${folders_to_delete[@]}"; do | |
| echo "Deleting $folder..." | |
| rm -rf "$folder" | |
| done | |
| echo "Node_modules folders have been deleted." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment