Last active
April 11, 2026 20:33
-
-
Save christophervigliotti/2c1f63924f11276963628ffd73e29a1d to your computer and use it in GitHub Desktop.
detailed comparison of files in "a" to files and hardlinks in "b"
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 | |
| # What Is This | |
| # A way to compare downloads in folder A to hardlinks in folder B. Useful to see if your | |
| # "use hardlinks" logic in the ARRS is working | |
| # | |
| # Separation of Concerns (AI yackin') | |
| # The logic for calculating the 2TB physical limit is isolated from the descriptive logic | |
| # used for the detailed file list. | |
| # | |
| # Storage Logic (AI yackin') | |
| # The math specifically accounts for the unique nature of hardlinks, ensuring you know exactly | |
| # how much "physical" space is left on your drive versus "apparent" space. | |
| # | |
| # Usage | |
| # make this executable | |
| # chmod +x arrs_inspector.sh | |
| # arrs_inspector.sh --overview | |
| # arrs_inspector.sh --detail | |
| # | |
| # More Terminal Fun! A few helpful one-liners | |
| # folders that contain more than one video file | |
| # find ~/files/downloads/movies -type f \( -iname "*.mp4" -o -iname "*.mkv" -o -iname "*.avi" -o -iname "*.m4v" -o -iname "*.mov" \) -printf "%h\n" | sort | uniq -c | awk '$1 > 1 {sub(/^[ \t]*[0-9]+ /, ""); print}' | xargs -I {} ls -lh {} | |
| # do I maybe need to upgrade soon? (prices and exchange rate hard-coded) | |
| # echo -e "Plan | Storage | Monthly (USD) | Visualization\n$(echo -e "Bat Box\nGremlin Box\nVampire Box\nZombie Box\nRed Dragon Box" | awk -v used=$(du -sb ~ 2>/dev/null | cut -f1) 'BEGIN{OFS="|"; eur2usd=1.17; split("2000,3000,4000,6000,12000", s, ","); split("14.35,18.85,27.85,36.85,72.85", p, ",")} {gb=s[NR]; usd=p[NR]*eur2usd; bar_total=40; used_gb=used/(1024^3); used_marks=int((used_gb/gb)*bar_total); if(used_marks<1 && used_gb>0) used_marks=1; printf "%-14s | %4.1f TB | $%7.2f | [", $0, gb/1000, usd; for(i=0; i<bar_total; i++) printf (i<used_marks ? "#" : "-"); printf "] %s\n", ($0=="Bat Box" ? sprintf("<< USED: %.1f GB (%.1f%%)", used_gb, (used_gb/gb)*100) : "")} END {print "\n* Pricing, exchange rate, and other deets subject to change."}')" | |
| # Configuration - Update these paths if your movie folders change | |
| DL_PATH="$HOME/files/downloads/movies" | |
| MD_PATH="$HOME/files/media/movies" | |
| # Colors for terminal output | |
| GREEN='\033[0;32m' | |
| BLUE='\033[0;34m' | |
| YELLOW='\033[1;33m' | |
| RED='\033[0;31m' | |
| NC='\033[0m' | |
| show_overview() { | |
| echo -e "${BLUE}--- Arrs Storage Overview ---${NC}" | |
| ( | |
| find "$DL_PATH" -type f -printf "dl %i %s\n" 2>/dev/null | |
| find "$MD_PATH" -type f -printf "md %i %s\n" 2>/dev/null | |
| ) | awk -v yellow="$YELLOW" -v green="$GREEN" -v nc="$NC" ' | |
| { | |
| type=$1; inode=$2; size=$3; | |
| # Count physical space (only count each unique inode once) | |
| if (!seen_inode[inode]++) { actual_sz += size } | |
| if (type == "dl") { | |
| dl_cnt++; dl_sz += size; dl_inodes[inode]++ | |
| } else if (type == "md") { | |
| md_cnt++; md_sz += size; | |
| if (inode in dl_inodes) { hl_cnt++; hl_sz += size } | |
| } | |
| } | |
| END { | |
| printf "Downloads Total: %d files (%.2f GB)\n", dl_cnt, dl_sz/1024^3; | |
| printf "Media Total: %d files (%.2f GB)\n", md_cnt, md_sz/1024^3; | |
| print "------------------------------------------"; | |
| printf "Actual Physical Space Used: %s%.2f GB%s\n", yellow, actual_sz/1024^3, nc; | |
| printf "Space Saved by Hardlinks: %s%.2f GB%s\n", green, (dl_sz+md_sz-actual_sz)/1024^3, nc; | |
| }' | |
| } | |
| show_detail() { | |
| echo -e "${BLUE}--- Detailed File Audit ---${NC}" | |
| find "$DL_PATH" "$MD_PATH" -type f -exec stat -c '%i %n' {} + 2>/dev/null | awk -v dl="$DL_PATH" -v md="$MD_PATH" -v green="$GREEN" -v red="$RED" -v nc="$NC" ' | |
| { | |
| inode=$1; $1=""; sub(/^ /, "", $0); fullpath=$0; | |
| filename=fullpath; gsub(/.*\//, "", filename); | |
| if (fullpath ~ dl) { in_dl[filename] = 1; dl_inode[filename] = inode } | |
| if (fullpath ~ md) { in_md[filename] = 1; md_inode[filename] = inode } | |
| } | |
| END { | |
| for (f in in_dl) all[f]; for (f in in_md) all[f]; | |
| for (f in all) { | |
| dl_status = (in_dl[f]) ? "exists" : "none "; | |
| if (!in_md[f]) { | |
| md_status = "none"; | |
| color = red; | |
| } else { | |
| if (in_dl[f] && dl_inode[f] == md_inode[f]) { | |
| md_status = "hardlinked"; | |
| color = green; | |
| } else { | |
| md_status = "COPY/FILE"; | |
| color = red; | |
| } | |
| } | |
| printf "[DL: %-7s] [MD: %s%-12s%s] %s\n", dl_status, color, md_status, nc, f; | |
| } | |
| }' | sort -k5 | |
| } | |
| # Main Execution Logic | |
| case "$1" in | |
| --overview) | |
| show_overview | |
| ;; | |
| --detail) | |
| show_detail | |
| ;; | |
| *) | |
| echo "Usage: $0 {--overview|--detail}" | |
| exit 1 | |
| ;; | |
| esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment