[{"data":1,"prerenderedAt":1649},["ShallowReactive",2],{"navigation_docs_en":3,"-en-nonsense-bash-servarr-duplicates-":377,"-en-nonsense-bash-servarr-duplicates--surround":1644},[4,16,94,262,271,332],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":15},"About","i-noto-star","\u002Fen\u002Fabout","en\u002F1.about",[10],{"title":11,"path":12,"stem":13,"icon":14},"Welcome","\u002Fen\u002Fabout\u002Fwelcome","en\u002F1.about\u002F1.welcome","i-lucide-home",false,{"title":17,"icon":18,"path":19,"stem":20,"children":21,"page":15},"General","i-noto-open-book","\u002Fen\u002Fgeneral","en\u002F2.general",[22,26,44,58,76],{"title":17,"path":23,"stem":24,"icon":25},"\u002Fen\u002Fgeneral\u002Fsummary","en\u002F2.general\u002F1.summary","i-lucide-bookmark",{"title":27,"icon":28,"path":29,"stem":30,"children":31,"page":15},"Networking","i-lucide-network","\u002Fen\u002Fgeneral\u002Fnetworking","en\u002F2.general\u002F2.networking",[32,36,40],{"title":33,"path":34,"stem":35},"NAT & DHCP","\u002Fen\u002Fgeneral\u002Fnetworking\u002Fnat","en\u002F2.general\u002F2.networking\u002F1.nat",{"title":37,"path":38,"stem":39},"DNS Zone","\u002Fen\u002Fgeneral\u002Fnetworking\u002Fdns","en\u002F2.general\u002F2.networking\u002F2.dns",{"title":41,"path":42,"stem":43},"Samba","\u002Fen\u002Fgeneral\u002Fnetworking\u002Fsamba","en\u002F2.general\u002F2.networking\u002F3.samba",{"title":45,"icon":46,"path":47,"stem":48,"children":49,"page":15},"Storage","i-lucide-hard-drive","\u002Fen\u002Fgeneral\u002Fstorage","en\u002F2.general\u002F3.storage",[50,54],{"title":51,"path":52,"stem":53},"RAID","\u002Fen\u002Fgeneral\u002Fstorage\u002Fraid","en\u002F2.general\u002F3.storage\u002F1.raid",{"title":55,"path":56,"stem":57},"ZFS","\u002Fen\u002Fgeneral\u002Fstorage\u002Fzfs","en\u002F2.general\u002F3.storage\u002F2.zfs",{"title":59,"icon":60,"path":61,"stem":62,"children":63,"page":15},"Hardware","i-lucide-server","\u002Fen\u002Fgeneral\u002Fhardware","en\u002F2.general\u002F4.hardware",[64,68,72],{"title":65,"path":66,"stem":67},"The Basics","\u002Fen\u002Fgeneral\u002Fhardware\u002Fbasics","en\u002F2.general\u002F4.hardware\u002F1.basics",{"title":69,"path":70,"stem":71},"Network","\u002Fen\u002Fgeneral\u002Fhardware\u002Fnetwork","en\u002F2.general\u002F4.hardware\u002F2.network",{"title":73,"path":74,"stem":75},"The ProloNAS","\u002Fen\u002Fgeneral\u002Fhardware\u002Fprolonas","en\u002F2.general\u002F4.hardware\u002F3.prolonas",{"title":77,"icon":78,"path":79,"stem":80,"children":81,"page":15},"Linux tips for dummies","i-lucide-terminal","\u002Fen\u002Fgeneral\u002Flinux","en\u002F2.general\u002F5.linux",[82,86,90],{"title":83,"path":84,"stem":85},"Command line basics","\u002Fen\u002Fgeneral\u002Flinux\u002Fcli-basics","en\u002F2.general\u002F5.linux\u002F1.cli-basics",{"title":87,"path":88,"stem":89},"Folders and partitions","\u002Fen\u002Fgeneral\u002Flinux\u002Ffilesystem","en\u002F2.general\u002F5.linux\u002F2.filesystem",{"title":91,"path":92,"stem":93},"Handy CLI tools","\u002Fen\u002Fgeneral\u002Flinux\u002Fhandy-tools","en\u002F2.general\u002F5.linux\u002F3.handy-tools",{"title":95,"icon":96,"path":97,"stem":98,"children":99,"page":15},"Serveex","i-noto-microscope","\u002Fen\u002Fserveex","en\u002F3.serveex",[100,104,126,144,170,188,202,216,234,248],{"title":101,"path":102,"stem":103,"icon":25},"Introduction","\u002Fen\u002Fserveex\u002Fintroduction","en\u002F3.serveex\u002F1.introduction",{"title":105,"icon":106,"path":107,"stem":108,"children":109,"page":15},"Server core","i-lucide-server-cog","\u002Fen\u002Fserveex\u002Fcore","en\u002F3.serveex\u002F2.core",[110,114,118,122],{"title":111,"path":112,"stem":113},"Debian 13","\u002Fen\u002Fserveex\u002Fcore\u002Finstallation","en\u002F3.serveex\u002F2.core\u002F1.installation",{"title":115,"path":116,"stem":117},"Docker","\u002Fen\u002Fserveex\u002Fcore\u002Fdocker","en\u002F3.serveex\u002F2.core\u002F2.docker",{"title":119,"path":120,"stem":121},"Wireguard","\u002Fen\u002Fserveex\u002Fcore\u002Fwireguard","en\u002F3.serveex\u002F2.core\u002F3.wireguard",{"title":123,"path":124,"stem":125},"SWAG","\u002Fen\u002Fserveex\u002Fcore\u002Fswag","en\u002F3.serveex\u002F2.core\u002F4.swag",{"title":127,"icon":128,"path":129,"stem":130,"children":131,"page":15},"Security","i-lucide-shield","\u002Fen\u002Fserveex\u002Fsecurity","en\u002F3.serveex\u002F3.security",[132,136,140],{"title":133,"path":134,"stem":135},"Cloudflare Zero Trust","\u002Fen\u002Fserveex\u002Fsecurity\u002Fcloudflare","en\u002F3.serveex\u002F3.security\u002F2.cloudflare",{"title":137,"path":138,"stem":139},"TinyAuth","\u002Fen\u002Fserveex\u002Fsecurity\u002Ftinyauth","en\u002F3.serveex\u002F3.security\u002F3.tinyauth",{"title":141,"path":142,"stem":143},"Pocket ID","\u002Fen\u002Fserveex\u002Fsecurity\u002Fpocket-id","en\u002F3.serveex\u002F3.security\u002F4.pocket-id",{"title":145,"icon":146,"path":147,"stem":148,"children":149,"page":15},"Monitoring","i-lucide-chart-no-axes-column","\u002Fen\u002Fserveex\u002Fmonitoring","en\u002F3.serveex\u002F4.monitoring",[150,154,158,162,166],{"title":151,"path":152,"stem":153},"Uptime-Kuma","\u002Fen\u002Fserveex\u002Fmonitoring\u002Fuptime-kuma","en\u002F3.serveex\u002F4.monitoring\u002F1.uptime-kuma",{"title":155,"path":156,"stem":157},"Dozzle","\u002Fen\u002Fserveex\u002Fmonitoring\u002Fdozzle","en\u002F3.serveex\u002F4.monitoring\u002F2.dozzle",{"title":159,"path":160,"stem":161},"Speedtest Tracker","\u002Fen\u002Fserveex\u002Fmonitoring\u002Fspeedtest-tracker","en\u002F3.serveex\u002F4.monitoring\u002F3.speedtest-tracker",{"title":163,"path":164,"stem":165},"Beszel","\u002Fen\u002Fserveex\u002Fmonitoring\u002Fbeszel","en\u002F3.serveex\u002F4.monitoring\u002F4.beszel",{"title":167,"path":168,"stem":169},"UpSnap","\u002Fen\u002Fserveex\u002Fmonitoring\u002Fupsnap","en\u002F3.serveex\u002F4.monitoring\u002F5.upsnap",{"title":171,"icon":172,"path":173,"stem":174,"children":175,"page":15},"Media & Seedbox","i-lucide-list-video","\u002Fen\u002Fserveex\u002Fmedia","en\u002F3.serveex\u002F5.media",[176,180,184],{"title":177,"path":178,"stem":179},"Jellyfin","\u002Fen\u002Fserveex\u002Fmedia\u002Fjellyfin","en\u002F3.serveex\u002F5.media\u002F1.jellyfin",{"title":181,"path":182,"stem":183},"Qbittorrent","\u002Fen\u002Fserveex\u002Fmedia\u002Fqbittorrent","en\u002F3.serveex\u002F5.media\u002F2.qbittorrent",{"title":185,"path":186,"stem":187},"Automation","\u002Fen\u002Fserveex\u002Fmedia\u002Fservarr","en\u002F3.serveex\u002F5.media\u002F3.servarr",{"title":189,"icon":190,"path":191,"stem":192,"children":193,"page":15},"Cloud Drive & Photos","i-lucide-cloud-upload","\u002Fen\u002Fserveex\u002Fcloud","en\u002F3.serveex\u002F6.cloud",[194,198],{"title":195,"path":196,"stem":197},"Immich","\u002Fen\u002Fserveex\u002Fcloud\u002Fimmich","en\u002F3.serveex\u002F6.cloud\u002F1.immich",{"title":199,"path":200,"stem":201},"Nextcloud","\u002Fen\u002Fserveex\u002Fcloud\u002Fnextcloud","en\u002F3.serveex\u002F6.cloud\u002F2.nextcloud",{"title":203,"icon":204,"path":205,"stem":206,"children":207,"page":15},"File & share","i-lucide-folder-tree","\u002Fen\u002Fserveex\u002Ffiles","en\u002F3.serveex\u002F7.files",[208,212],{"title":209,"path":210,"stem":211},"File Browser Quantum","\u002Fen\u002Fserveex\u002Ffiles\u002Ffile-browser-quantum","en\u002F3.serveex\u002F7.files\u002F1.file-browser-quantum",{"title":213,"path":214,"stem":215},"Pingvin","\u002Fen\u002Fserveex\u002Ffiles\u002Fpingvin","en\u002F3.serveex\u002F7.files\u002F2.pingvin",{"title":217,"icon":218,"path":219,"stem":220,"children":221,"page":15},"Developpement","i-lucide-code-xml","\u002Fen\u002Fserveex\u002Fdevelopment","en\u002F3.serveex\u002F8.development",[222,226,230],{"title":223,"path":224,"stem":225},"Code-Server","\u002Fen\u002Fserveex\u002Fdevelopment\u002Fcode-server","en\u002F3.serveex\u002F8.development\u002F1.code-server",{"title":227,"path":228,"stem":229},"Forgejo","\u002Fen\u002Fserveex\u002Fdevelopment\u002Fforgejo","en\u002F3.serveex\u002F8.development\u002F2.forgejo",{"title":231,"path":232,"stem":233},"IT Tools","\u002Fen\u002Fserveex\u002Fdevelopment\u002Fit-tools","en\u002F3.serveex\u002F8.development\u002F3.it-tools",{"title":235,"icon":236,"path":237,"stem":238,"children":239,"page":15},"Useful Apps","i-lucide-award","\u002Fen\u002Fserveex\u002Fapps","en\u002F3.serveex\u002F9.apps",[240,244],{"title":241,"path":242,"stem":243},"Adguard Home","\u002Fen\u002Fserveex\u002Fapps\u002Fadguard","en\u002F3.serveex\u002F9.apps\u002F1.adguard",{"title":245,"path":246,"stem":247},"Vaultwarden","\u002Fen\u002Fserveex\u002Fapps\u002Fvaultwarden","en\u002F3.serveex\u002F9.apps\u002F2.vaultwarden",{"title":249,"icon":250,"path":251,"stem":252,"children":253,"page":15},"Advanced","i-lucide-flask-conical","\u002Fen\u002Fserveex\u002Fadvanced","en\u002F3.serveex\u002F91.advanced",[254,258],{"title":255,"path":256,"stem":257},"Authentik","\u002Fen\u002Fserveex\u002Fadvanced\u002Fauthentik","en\u002F3.serveex\u002F91.advanced\u002F1.authentik",{"title":259,"path":260,"stem":261},"Arcane","\u002Fen\u002Fserveex\u002Fadvanced\u002Farcane","en\u002F3.serveex\u002F91.advanced\u002F2.arcane",{"title":263,"icon":264,"path":265,"stem":266,"children":267,"page":15},"Stockeex","i-noto-computer-disk","\u002Fen\u002Fstockeex","en\u002F4.stockeex",[268],{"title":101,"path":269,"stem":270,"icon":25},"\u002Fen\u002Fstockeex\u002Fintroduction","en\u002F4.stockeex\u002F1.introduction",{"title":272,"icon":273,"path":274,"stem":275,"children":276,"page":15},"My nonsense","i-noto-test-tube","\u002Fen\u002Fnonsense","en\u002F5.nonsense",[277,280,302],{"title":272,"path":278,"stem":279,"icon":25},"\u002Fen\u002Fnonsense\u002Fsummary","en\u002F5.nonsense\u002F1.summary",{"title":281,"icon":282,"path":283,"stem":284,"children":285,"page":15},"Python","i-lucide-file-code-2","\u002Fen\u002Fnonsense\u002Fpython","en\u002F5.nonsense\u002F2.python",[286,290,294,298],{"title":287,"path":288,"stem":289},"Nvidia Stock Bot","\u002Fen\u002Fnonsense\u002Fpython\u002Fnvidia-stock-bot","en\u002F5.nonsense\u002F2.python\u002F1.nvidia-stock-bot",{"title":291,"path":292,"stem":293},"Adguard CIDRE","\u002Fen\u002Fnonsense\u002Fpython\u002Fadguard-cidre","en\u002F5.nonsense\u002F2.python\u002F2.adguard-cidre",{"title":295,"path":296,"stem":297},"Lumeex","\u002Fen\u002Fnonsense\u002Fpython\u002Flumeex","en\u002F5.nonsense\u002F2.python\u002F3.lumeex",{"title":299,"path":300,"stem":301},"Instameex","\u002Fen\u002Fnonsense\u002Fpython\u002Finstameex","en\u002F5.nonsense\u002F2.python\u002F4.instameex",{"title":303,"icon":304,"path":305,"stem":306,"children":307,"page":15},"Bash","i-lucide-file-terminal","\u002Fen\u002Fnonsense\u002Fbash","en\u002F5.nonsense\u002F3.bash",[308,312,316,320,324,328],{"title":309,"path":310,"stem":311},"Servarr corrector","\u002Fen\u002Fnonsense\u002Fbash\u002Fservarr-duplicates","en\u002F5.nonsense\u002F3.bash\u002F1.servarr-duplicates",{"title":313,"path":314,"stem":315},"LUKS Backup","\u002Fen\u002Fnonsense\u002Fbash\u002Fluks-backup","en\u002F5.nonsense\u002F3.bash\u002F2.luks-backup",{"title":317,"path":318,"stem":319},"Socat Proxy","\u002Fen\u002Fnonsense\u002Fbash\u002Fsocat-proxy","en\u002F5.nonsense\u002F3.bash\u002F3.socat-proxy",{"title":321,"path":322,"stem":323},"HotDisk","\u002Fen\u002Fnonsense\u002Fbash\u002Fhotdisk","en\u002F5.nonsense\u002F3.bash\u002F4.hotdisk",{"title":325,"path":326,"stem":327},"Backrest Docker Stop","\u002Fen\u002Fnonsense\u002Fbash\u002Fbackrest-docker-stop","en\u002F5.nonsense\u002F3.bash\u002F5.backrest-docker-stop",{"title":329,"path":330,"stem":331},"rm Confirmation Guard","\u002Fen\u002Fnonsense\u002Fbash\u002Frm-confirmation","en\u002F5.nonsense\u002F3.bash\u002F6.rm-confirmation",{"title":333,"icon":334,"path":335,"stem":336,"children":337,"page":15},"Recycled","i-noto-recycling-symbol","\u002Fen\u002Frecycled","en\u002F6.recycled",[338,341,355],{"title":333,"path":339,"stem":340,"icon":25},"\u002Fen\u002Frecycled\u002Fsummary","en\u002F6.recycled\u002F1.summary",{"title":342,"icon":343,"path":344,"stem":345,"children":346,"page":15},"Deprecated","i-lucide-trash-2","\u002Fen\u002Frecycled\u002Fdeprecated","en\u002F6.recycled\u002F2.deprecated",[347,351],{"title":348,"path":349,"stem":350},"Wireguard 14","\u002Fen\u002Frecycled\u002Fdeprecated\u002Fwireguard-14","en\u002F6.recycled\u002F2.deprecated\u002F1.wireguard-14",{"title":352,"path":353,"stem":354},"File Browser","\u002Fen\u002Frecycled\u002Fdeprecated\u002Ffile-browser","en\u002F6.recycled\u002F2.deprecated\u002F2.file-browser",{"title":356,"icon":357,"path":358,"stem":359,"children":360,"page":15},"Alternatives","i-lucide-arrow-left-right","\u002Fen\u002Frecycled\u002Falternatives","en\u002F6.recycled\u002F3.alternatives",[361,365,369,373],{"title":362,"path":363,"stem":364},"Plex","\u002Fen\u002Frecycled\u002Falternatives\u002Fplex","en\u002F6.recycled\u002F3.alternatives\u002F1.plex",{"title":366,"path":367,"stem":368},"Qbittorrent for Plex","\u002Fen\u002Frecycled\u002Falternatives\u002Fqbittorrent-for-plex","en\u002F6.recycled\u002F3.alternatives\u002F2.qbittorrent for plex",{"title":370,"path":371,"stem":372},"Servarr for Plex","\u002Fen\u002Frecycled\u002Falternatives\u002Fservarr-for-plex","en\u002F6.recycled\u002F3.alternatives\u002F3.servarr for plex",{"title":374,"path":375,"stem":376},"Gitea","\u002Fen\u002Frecycled\u002Falternatives\u002Fgitea","en\u002F6.recycled\u002F3.alternatives\u002F4.gitea",{"id":378,"title":309,"body":379,"contributors":1636,"description":1638,"extension":1639,"hideCopyPage":15,"hideHeader":15,"hideToc":15,"links":1640,"meta":1641,"navigation":498,"path":310,"seo":1642,"stem":311,"__hash__":1643},"docs_en\u002Fen\u002F5.nonsense\u002F3.bash\u002F1.servarr-duplicates.md",{"type":380,"value":381,"toc":1634},"minimark",[382,390,410,413,418,436,439,458,461,468,471,474,909,912,920,931,934,942,945,1613,1616,1630],[383,384],"ellipsis",{"blur":385,"left":386,"top":387,"width":388,"z-index":389},"140px","0px","10rem","40rem","60",[391,392,393,394,398,399,398,402,405,406,409],"p",{},"Six months after downloading terabytes of media, I realized that Sonarr and Radarr were copying them into my Plex library instead of creating hardlinks. This happens due to a counterintuitive mechanism: if you mount multiple folders in Sonarr\u002FRadarr, it sees them as different filesystems and thus cannot create hardlinks. That’s why you should mount only one parent folder containing all child folders (like ",[395,396,397],"code",{},"downloads",", ",[395,400,401],{},"movies",[395,403,404],{},"tvseries"," inside a ",[395,407,408],{},"media"," parent folder).",[391,411,412],{},"So I restructured my directories, manually updated every path in Qbittorrent, Plex, and others. The last challenge was finding a way to detect existing duplicates, delete them, and automatically create hardlinks instead, to save space.",[414,415],"file-tree",{":tree":416,"label":417},"[[[{\"media\":[\"seedbox\u002F\",{\"radarr\":[\"tv-radarr\u002F\"]},\"movies\u002F\",\"tvseries\u002F\"]}]]]","My directory structure",[391,419,420,421,424,425,427,428,430,431,427,433,435],{},"The originals are in ",[395,422,423],{},"seedbox"," and must not be modified to keep seeding. The copies (duplicates) are in ",[395,426,401],{}," and ",[395,429,404],{},". To complicate things, there are also unique originals in ",[395,432,401],{},[395,434,404],{},". And within those, there can be subfolders, sub-subfolders, etc.",[391,437,438],{},"So the idea is to:",[440,441,442,446,449,452,455],"ul",{},[443,444,445],"li",{},"list the originals in seedbox",[443,447,448],{},"list files in movies and tvseries",[443,450,451],{},"compare both lists and isolate duplicates",[443,453,454],{},"delete the duplicates",[443,456,457],{},"hardlink the originals to the deleted duplicate paths",[391,459,460],{},"Yes, I asked ChatGPT and Qwen3 (which I host on a dedicated AI machine). Naturally, they suggested tools like rfind, rdfind, dupes, rdupes, rmlint... But hashing 30TB of media would take days, so I gave up quickly.",[391,462,463,464,467],{},"In the end, I only needed to find ",[395,465,466],{},".mkv"," files, and duplicates have the exact same name as the originals, which simplifies things a lot. A simple Bash script would do the job.",[391,469,470],{},"Spare you the endless Q&A with ChatGPT, I was disappointed. Qwen3 was much cleaner. ChatGPT kept pushing awk-based solutions, which fail on paths with spaces. With Qwen’s help and dropping awk, the results improved significantly.",[391,472,473],{},"To test, I first asked for a script that only lists and compares:",[475,476,482],"pre",{"className":477,"code":478,"filename":479,"language":480,"meta":481,"style":481},"language-bash shiki shiki-themes github-dark material-theme github-dark","#!\u002Fbin\u002Fbash\n\n# Create an associative array to store duplicates\ndeclare -A seen\n\n# Find all .mkv files only (exclude directories)\nfind \u002Fmedia\u002Fseedbox \u002Fmedia\u002Fmovies \u002Fmedia\u002Ftvseries -type f -name \"*.mkv\" -print0 | \\\nwhile IFS= read -r -d '' file; do\n    # Get the file's inode and name\n    inode=$(stat --format=\"%i\" \"$file\")\n    filename=$(basename \"$file\")\n    \n    # If the filename has been seen before\n    if [[ -n \"${seen[$filename]}\" ]]; then\n        # Check if the inode is different from the previous one\n        if [[ \"${seen[$filename]}\" != \"$inode\" ]]; then\n            # Output the duplicates with full paths\n            echo \"Duplicates for \\\"$filename\\\":\"\n            echo \"${seen[\"$filename\"]} ${seen[\"$filename:full_path\"]}\"\n            echo \"$inode $file\"\n            echo\n        fi\n    else\n        seen[$filename]=\"$inode\"\n        seen[\"$filename:full_path\"]=\"$file\"\n    fi\ndone\n","Terminal","bash","",[395,483,484,493,500,506,521,526,532,579,614,620,655,676,682,688,721,727,759,765,789,821,835,841,847,853,874,897,903],{"__ignoreMap":481},[485,486,489],"span",{"class":487,"line":488},"line",1,[485,490,492],{"class":491},"sDvJj","#!\u002Fbin\u002Fbash\n",[485,494,496],{"class":487,"line":495},2,[485,497,499],{"emptyLinePlaceholder":498},true,"\n",[485,501,503],{"class":487,"line":502},3,[485,504,505],{"class":491},"# Create an associative array to store duplicates\n",[485,507,509,513,517],{"class":487,"line":508},4,[485,510,512],{"class":511},"sAoO4","declare",[485,514,516],{"class":515},"sJWha"," -A",[485,518,520],{"class":519},"slcoZ"," seen\n",[485,522,524],{"class":487,"line":523},5,[485,525,499],{"emptyLinePlaceholder":498},[485,527,529],{"class":487,"line":528},6,[485,530,531],{"class":491},"# Find all .mkv files only (exclude directories)\n",[485,533,535,539,543,546,549,552,555,558,562,565,568,571,575],{"class":487,"line":534},7,[485,536,538],{"class":537},"sEgDM","find",[485,540,542],{"class":541},"s11XM"," \u002Fmedia\u002Fseedbox",[485,544,545],{"class":541}," \u002Fmedia\u002Fmovies",[485,547,548],{"class":541}," \u002Fmedia\u002Ftvseries",[485,550,551],{"class":515}," -type",[485,553,554],{"class":541}," f",[485,556,557],{"class":515}," -name",[485,559,561],{"class":560},"s8K8j"," \"",[485,563,564],{"class":541},"*.mkv",[485,566,567],{"class":560},"\"",[485,569,570],{"class":515}," -print0",[485,572,574],{"class":573},"sJPTy"," |",[485,576,578],{"class":577},"s8-mJ"," \\\n",[485,580,582,586,589,592,595,598,601,604,607,611],{"class":487,"line":581},8,[485,583,585],{"class":584},"sJLGa","while",[485,587,588],{"class":541}," IFS",[485,590,591],{"class":573},"=",[485,593,594],{"class":541}," read",[485,596,597],{"class":515}," -r",[485,599,600],{"class":515}," -d",[485,602,603],{"class":560}," ''",[485,605,606],{"class":541}," file",[485,608,610],{"class":609},"s8jd1",";",[485,612,613],{"class":584}," do\n",[485,615,617],{"class":487,"line":616},9,[485,618,619],{"class":491},"    # Get the file's inode and name\n",[485,621,623,626,628,631,635,638,640,643,645,647,650,652],{"class":487,"line":622},10,[485,624,625],{"class":519},"    inode",[485,627,591],{"class":573},[485,629,630],{"class":609},"$(",[485,632,634],{"class":633},"sJGgK","stat",[485,636,637],{"class":515}," --format=",[485,639,567],{"class":560},[485,641,642],{"class":541},"%i",[485,644,567],{"class":560},[485,646,561],{"class":560},[485,648,649],{"class":519},"$file",[485,651,567],{"class":560},[485,653,654],{"class":609},")\n",[485,656,658,661,663,665,668,670,672,674],{"class":487,"line":657},11,[485,659,660],{"class":519},"    filename",[485,662,591],{"class":573},[485,664,630],{"class":609},[485,666,667],{"class":537},"basename",[485,669,561],{"class":560},[485,671,649],{"class":519},[485,673,567],{"class":560},[485,675,654],{"class":609},[485,677,679],{"class":487,"line":678},12,[485,680,681],{"class":519},"    \n",[485,683,685],{"class":487,"line":684},13,[485,686,687],{"class":491},"    # If the filename has been seen before\n",[485,689,691,694,697,700,703,706,709,712,715,718],{"class":487,"line":690},14,[485,692,693],{"class":584},"    if",[485,695,696],{"class":609}," [[",[485,698,699],{"class":573}," -n",[485,701,702],{"class":560}," \"${",[485,704,705],{"class":519},"seen",[485,707,708],{"class":560},"[",[485,710,711],{"class":519},"$filename",[485,713,714],{"class":560},"]}\"",[485,716,717],{"class":609}," ]];",[485,719,720],{"class":584}," then\n",[485,722,724],{"class":487,"line":723},15,[485,725,726],{"class":491},"        # Check if the inode is different from the previous one\n",[485,728,730,733,735,737,739,741,743,745,748,750,753,755,757],{"class":487,"line":729},16,[485,731,732],{"class":584},"        if",[485,734,696],{"class":609},[485,736,702],{"class":560},[485,738,705],{"class":519},[485,740,708],{"class":560},[485,742,711],{"class":519},[485,744,714],{"class":560},[485,746,747],{"class":573}," !=",[485,749,561],{"class":560},[485,751,752],{"class":519},"$inode",[485,754,567],{"class":560},[485,756,717],{"class":609},[485,758,720],{"class":584},[485,760,762],{"class":487,"line":761},17,[485,763,764],{"class":491},"            # Output the duplicates with full paths\n",[485,766,768,771,773,776,779,781,783,786],{"class":487,"line":767},18,[485,769,770],{"class":633},"            echo",[485,772,561],{"class":560},[485,774,775],{"class":541},"Duplicates for ",[485,777,778],{"class":577},"\\\"",[485,780,711],{"class":519},[485,782,778],{"class":577},[485,784,785],{"class":541},":",[485,787,788],{"class":560},"\"\n",[485,790,792,794,796,798,801,803,806,809,811,813,815,818],{"class":487,"line":791},19,[485,793,770],{"class":633},[485,795,702],{"class":560},[485,797,705],{"class":519},[485,799,800],{"class":560},"[\"",[485,802,711],{"class":519},[485,804,805],{"class":560},"\"]}",[485,807,808],{"class":560}," ${",[485,810,705],{"class":519},[485,812,800],{"class":560},[485,814,711],{"class":519},[485,816,817],{"class":541},":full_path",[485,819,820],{"class":560},"\"]}\"\n",[485,822,824,826,828,830,833],{"class":487,"line":823},20,[485,825,770],{"class":633},[485,827,561],{"class":560},[485,829,752],{"class":519},[485,831,832],{"class":519}," $file",[485,834,788],{"class":560},[485,836,838],{"class":487,"line":837},21,[485,839,840],{"class":633},"            echo\n",[485,842,844],{"class":487,"line":843},22,[485,845,846],{"class":584},"        fi\n",[485,848,850],{"class":487,"line":849},23,[485,851,852],{"class":584},"    else\n",[485,854,856,859,861,863,866,868,870,872],{"class":487,"line":855},24,[485,857,858],{"class":519},"        seen",[485,860,708],{"class":609},[485,862,711],{"class":519},[485,864,865],{"class":609},"]",[485,867,591],{"class":573},[485,869,567],{"class":560},[485,871,752],{"class":519},[485,873,788],{"class":560},[485,875,877,880,882,884,887,889,891,893,895],{"class":487,"line":876},25,[485,878,879],{"class":537},"        seen[",[485,881,567],{"class":537},[485,883,711],{"class":519},[485,885,886],{"class":537},":full_path\"",[485,888,865],{"class":537},[485,890,591],{"class":541},[485,892,567],{"class":537},[485,894,649],{"class":519},[485,896,788],{"class":537},[485,898,900],{"class":487,"line":899},26,[485,901,902],{"class":584},"    fi\n",[485,904,906],{"class":487,"line":905},27,[485,907,908],{"class":584},"done\n",[391,910,911],{},"This gave me outputs like:",[475,913,918],{"className":914,"code":916,"language":917},[915],"language-text","Duplicates for \"episode1.mkv\":\n1234567 \u002Fmedia\u002Fseedbox\u002Fsonarr\u002FSerie 1\u002FSeason1\u002Fepisode1.mkv\n2345678 \u002Fmedia\u002Ftvseries\u002FSerie 1\u002FSeason1\u002Fepisode1.mkv\n","text",[395,919,916],{"__ignoreMap":481},[391,921,922,923,926,927,930],{},"With ",[395,924,925],{},"awk",", it would’ve stopped at ",[395,928,929],{},"\u002Fmedia\u002Fseedbox\u002Fsonarr\u002FSerie",". I’m far from an expert, but Qwen3 performed better and explained everything clearly.",[391,932,933],{},"Once I verified the output, I asked for a complete script: compare, delete duplicates, create hardlinks.",[391,935,936,937,941],{},"Again, ChatGPT disappointed. Despite my requests, it created hardlinks ",[938,939,940],"em",{},"before"," deleting the duplicates, effectively linking and then deleting the link (though the original is kept). Not helpful.",[391,943,944],{},"Quick stopover to Qwen3, RTX 5090 in overdrive, and bam, much better result. Yes, it kept ChatGPT-style emojis, but here it is:",[475,946,948],{"className":477,"code":947,"filename":479,"language":480,"meta":481,"style":481},"#!\u002Fbin\u002Fbash\n\necho \"🔍 Step 1: Indexing original files in \u002Fmedia\u002Fseedbox...\"\ndeclare -A seen\n\n# Index all .mkv files in seedbox\nwhile IFS= read -r -d '' file; do\n    filename=$(basename \"$file\")\n    seen[\"$filename\"]=\"$file\"\ndone \u003C \u003C(find \u002Fmedia\u002Fseedbox -type f -name \"*.mkv\" -print0)\n\necho \"📦 Step 2: Automatically replacing duplicates...\"\ntotal_doublons=0\ntotal_ko_saved=0\n\nwhile IFS= read -r -d '' file; do\n    filename=$(basename \"$file\")\n    original=\"${seen[$filename]}\"\n\n    if [[ -n \"$original\" && \"$original\" != \"$file\" ]]; then\n        inode_orig=$(stat -c %i \"$original\")\n        inode_dupe=$(stat -c %i \"$file\")\n\n        if [[ \"$inode_orig\" != \"$inode_dupe\" ]]; then\n            size_kb=$(du -k \"$file\" | cut -f1)\n            echo \"🔁 Replacing:\"\n            echo \"    Duplicate : $file\"\n            echo \"    Original  : $original\"\n            echo \"    Size      : ${size_kb} KB\"\n\n            rm \"$file\" && ln \"$original\" \"$file\" && echo \"✅ Hardlink created.\"\n\n            total_doublons=$((total_doublons + 1))\n            total_ko_saved=$((total_ko_saved + size_kb))\n        fi\n    fi\ndone \u003C \u003C(find \u002Fmedia\u002Fmovies \u002Fmedia\u002Ftvseries -type f -name \"*.mkv\" -print0)\n\necho \"\"\necho \"🧾 Summary:\"\necho \"    🔗 Duplicates replaced by hardlink: $total_doublons\"\necho \"    💾 Approx. disk space saved: ${total_ko_saved} KB (~$((total_ko_saved \u002F 1024)) MB)\"\necho \"✅ Done.\"\n",[395,949,950,954,958,970,978,982,987,1009,1027,1048,1083,1087,1098,1108,1117,1121,1143,1161,1180,1184,1220,1245,1268,1272,1298,1329,1340,1353,1367,1391,1396,1437,1442,1465,1484,1489,1494,1524,1529,1537,1549,1564,1601],{"__ignoreMap":481},[485,951,952],{"class":487,"line":488},[485,953,492],{"class":491},[485,955,956],{"class":487,"line":495},[485,957,499],{"emptyLinePlaceholder":498},[485,959,960,963,965,968],{"class":487,"line":502},[485,961,962],{"class":633},"echo",[485,964,561],{"class":560},[485,966,967],{"class":541},"🔍 Step 1: Indexing original files in \u002Fmedia\u002Fseedbox...",[485,969,788],{"class":560},[485,971,972,974,976],{"class":487,"line":508},[485,973,512],{"class":511},[485,975,516],{"class":515},[485,977,520],{"class":519},[485,979,980],{"class":487,"line":523},[485,981,499],{"emptyLinePlaceholder":498},[485,983,984],{"class":487,"line":528},[485,985,986],{"class":491},"# Index all .mkv files in seedbox\n",[485,988,989,991,993,995,997,999,1001,1003,1005,1007],{"class":487,"line":534},[485,990,585],{"class":584},[485,992,588],{"class":519},[485,994,591],{"class":573},[485,996,594],{"class":633},[485,998,597],{"class":515},[485,1000,600],{"class":515},[485,1002,603],{"class":560},[485,1004,606],{"class":541},[485,1006,610],{"class":609},[485,1008,613],{"class":584},[485,1010,1011,1013,1015,1017,1019,1021,1023,1025],{"class":487,"line":581},[485,1012,660],{"class":519},[485,1014,591],{"class":573},[485,1016,630],{"class":609},[485,1018,667],{"class":537},[485,1020,561],{"class":560},[485,1022,649],{"class":519},[485,1024,567],{"class":560},[485,1026,654],{"class":609},[485,1028,1029,1032,1034,1036,1038,1040,1042,1044,1046],{"class":487,"line":616},[485,1030,1031],{"class":537},"    seen[",[485,1033,567],{"class":537},[485,1035,711],{"class":519},[485,1037,567],{"class":537},[485,1039,865],{"class":537},[485,1041,591],{"class":541},[485,1043,567],{"class":537},[485,1045,649],{"class":519},[485,1047,788],{"class":537},[485,1049,1050,1053,1056,1059,1061,1064,1067,1070,1073,1075,1077,1079,1081],{"class":487,"line":622},[485,1051,1052],{"class":584},"done",[485,1054,1055],{"class":573}," \u003C",[485,1057,1058],{"class":560}," \u003C(",[485,1060,538],{"class":537},[485,1062,1063],{"class":541}," \u002Fmedia\u002Fseedbox ",[485,1065,1066],{"class":515},"-type",[485,1068,1069],{"class":541}," f ",[485,1071,1072],{"class":515},"-name",[485,1074,561],{"class":560},[485,1076,564],{"class":541},[485,1078,567],{"class":560},[485,1080,570],{"class":515},[485,1082,654],{"class":560},[485,1084,1085],{"class":487,"line":657},[485,1086,499],{"emptyLinePlaceholder":498},[485,1088,1089,1091,1093,1096],{"class":487,"line":678},[485,1090,962],{"class":633},[485,1092,561],{"class":560},[485,1094,1095],{"class":541},"📦 Step 2: Automatically replacing duplicates...",[485,1097,788],{"class":560},[485,1099,1100,1103,1105],{"class":487,"line":684},[485,1101,1102],{"class":519},"total_doublons",[485,1104,591],{"class":573},[485,1106,1107],{"class":541},"0\n",[485,1109,1110,1113,1115],{"class":487,"line":690},[485,1111,1112],{"class":519},"total_ko_saved",[485,1114,591],{"class":573},[485,1116,1107],{"class":541},[485,1118,1119],{"class":487,"line":723},[485,1120,499],{"emptyLinePlaceholder":498},[485,1122,1123,1125,1127,1129,1131,1133,1135,1137,1139,1141],{"class":487,"line":729},[485,1124,585],{"class":584},[485,1126,588],{"class":519},[485,1128,591],{"class":573},[485,1130,594],{"class":633},[485,1132,597],{"class":515},[485,1134,600],{"class":515},[485,1136,603],{"class":560},[485,1138,606],{"class":541},[485,1140,610],{"class":609},[485,1142,613],{"class":584},[485,1144,1145,1147,1149,1151,1153,1155,1157,1159],{"class":487,"line":761},[485,1146,660],{"class":519},[485,1148,591],{"class":573},[485,1150,630],{"class":609},[485,1152,667],{"class":537},[485,1154,561],{"class":560},[485,1156,649],{"class":519},[485,1158,567],{"class":560},[485,1160,654],{"class":609},[485,1162,1163,1166,1168,1171,1173,1175,1177],{"class":487,"line":767},[485,1164,1165],{"class":519},"    original",[485,1167,591],{"class":573},[485,1169,1170],{"class":560},"\"${",[485,1172,705],{"class":519},[485,1174,708],{"class":560},[485,1176,711],{"class":519},[485,1178,1179],{"class":560},"]}\"\n",[485,1181,1182],{"class":487,"line":791},[485,1183,499],{"emptyLinePlaceholder":498},[485,1185,1186,1188,1190,1192,1194,1197,1199,1202,1204,1206,1208,1210,1212,1214,1216,1218],{"class":487,"line":823},[485,1187,693],{"class":584},[485,1189,696],{"class":609},[485,1191,699],{"class":573},[485,1193,561],{"class":560},[485,1195,1196],{"class":519},"$original",[485,1198,567],{"class":560},[485,1200,1201],{"class":573}," &&",[485,1203,561],{"class":560},[485,1205,1196],{"class":519},[485,1207,567],{"class":560},[485,1209,747],{"class":573},[485,1211,561],{"class":560},[485,1213,649],{"class":519},[485,1215,567],{"class":560},[485,1217,717],{"class":609},[485,1219,720],{"class":584},[485,1221,1222,1225,1227,1229,1231,1234,1237,1239,1241,1243],{"class":487,"line":837},[485,1223,1224],{"class":519},"        inode_orig",[485,1226,591],{"class":573},[485,1228,630],{"class":609},[485,1230,634],{"class":633},[485,1232,1233],{"class":515}," -c",[485,1235,1236],{"class":541}," %i",[485,1238,561],{"class":560},[485,1240,1196],{"class":519},[485,1242,567],{"class":560},[485,1244,654],{"class":609},[485,1246,1247,1250,1252,1254,1256,1258,1260,1262,1264,1266],{"class":487,"line":843},[485,1248,1249],{"class":519},"        inode_dupe",[485,1251,591],{"class":573},[485,1253,630],{"class":609},[485,1255,634],{"class":633},[485,1257,1233],{"class":515},[485,1259,1236],{"class":541},[485,1261,561],{"class":560},[485,1263,649],{"class":519},[485,1265,567],{"class":560},[485,1267,654],{"class":609},[485,1269,1270],{"class":487,"line":849},[485,1271,499],{"emptyLinePlaceholder":498},[485,1273,1274,1276,1278,1280,1283,1285,1287,1289,1292,1294,1296],{"class":487,"line":855},[485,1275,732],{"class":584},[485,1277,696],{"class":609},[485,1279,561],{"class":560},[485,1281,1282],{"class":519},"$inode_orig",[485,1284,567],{"class":560},[485,1286,747],{"class":573},[485,1288,561],{"class":560},[485,1290,1291],{"class":519},"$inode_dupe",[485,1293,567],{"class":560},[485,1295,717],{"class":609},[485,1297,720],{"class":584},[485,1299,1300,1303,1305,1307,1310,1313,1315,1317,1319,1321,1324,1327],{"class":487,"line":876},[485,1301,1302],{"class":519},"            size_kb",[485,1304,591],{"class":573},[485,1306,630],{"class":609},[485,1308,1309],{"class":537},"du",[485,1311,1312],{"class":515}," -k",[485,1314,561],{"class":560},[485,1316,649],{"class":519},[485,1318,567],{"class":560},[485,1320,574],{"class":573},[485,1322,1323],{"class":537}," cut",[485,1325,1326],{"class":515}," -f1",[485,1328,654],{"class":609},[485,1330,1331,1333,1335,1338],{"class":487,"line":899},[485,1332,770],{"class":633},[485,1334,561],{"class":560},[485,1336,1337],{"class":541},"🔁 Replacing:",[485,1339,788],{"class":560},[485,1341,1342,1344,1346,1349,1351],{"class":487,"line":905},[485,1343,770],{"class":633},[485,1345,561],{"class":560},[485,1347,1348],{"class":541},"    Duplicate : ",[485,1350,649],{"class":519},[485,1352,788],{"class":560},[485,1354,1356,1358,1360,1363,1365],{"class":487,"line":1355},28,[485,1357,770],{"class":633},[485,1359,561],{"class":560},[485,1361,1362],{"class":541},"    Original  : ",[485,1364,1196],{"class":519},[485,1366,788],{"class":560},[485,1368,1370,1372,1374,1377,1380,1383,1386,1389],{"class":487,"line":1369},29,[485,1371,770],{"class":633},[485,1373,561],{"class":560},[485,1375,1376],{"class":541},"    Size      : ",[485,1378,1379],{"class":560},"${",[485,1381,1382],{"class":519},"size_kb",[485,1384,1385],{"class":560},"}",[485,1387,1388],{"class":541}," KB",[485,1390,788],{"class":560},[485,1392,1394],{"class":487,"line":1393},30,[485,1395,499],{"emptyLinePlaceholder":498},[485,1397,1399,1402,1404,1406,1408,1410,1413,1415,1417,1419,1421,1423,1425,1427,1430,1432,1435],{"class":487,"line":1398},31,[485,1400,1401],{"class":537},"            rm",[485,1403,561],{"class":560},[485,1405,649],{"class":519},[485,1407,567],{"class":560},[485,1409,1201],{"class":609},[485,1411,1412],{"class":537}," ln",[485,1414,561],{"class":560},[485,1416,1196],{"class":519},[485,1418,567],{"class":560},[485,1420,561],{"class":560},[485,1422,649],{"class":519},[485,1424,567],{"class":560},[485,1426,1201],{"class":609},[485,1428,1429],{"class":633}," echo",[485,1431,561],{"class":560},[485,1433,1434],{"class":541},"✅ Hardlink created.",[485,1436,788],{"class":560},[485,1438,1440],{"class":487,"line":1439},32,[485,1441,499],{"emptyLinePlaceholder":498},[485,1443,1445,1448,1450,1453,1455,1458,1462],{"class":487,"line":1444},33,[485,1446,1447],{"class":519},"            total_doublons",[485,1449,591],{"class":573},[485,1451,1452],{"class":609},"$((",[485,1454,1102],{"class":537},[485,1456,1457],{"class":541}," +",[485,1459,1461],{"class":1460},"swwWl"," 1",[485,1463,1464],{"class":609},"))\n",[485,1466,1468,1471,1473,1475,1477,1479,1482],{"class":487,"line":1467},34,[485,1469,1470],{"class":519},"            total_ko_saved",[485,1472,591],{"class":573},[485,1474,1452],{"class":609},[485,1476,1112],{"class":537},[485,1478,1457],{"class":541},[485,1480,1481],{"class":541}," size_kb",[485,1483,1464],{"class":609},[485,1485,1487],{"class":487,"line":1486},35,[485,1488,846],{"class":584},[485,1490,1492],{"class":487,"line":1491},36,[485,1493,902],{"class":584},[485,1495,1497,1499,1501,1503,1505,1508,1510,1512,1514,1516,1518,1520,1522],{"class":487,"line":1496},37,[485,1498,1052],{"class":584},[485,1500,1055],{"class":573},[485,1502,1058],{"class":560},[485,1504,538],{"class":537},[485,1506,1507],{"class":541}," \u002Fmedia\u002Fmovies \u002Fmedia\u002Ftvseries ",[485,1509,1066],{"class":515},[485,1511,1069],{"class":541},[485,1513,1072],{"class":515},[485,1515,561],{"class":560},[485,1517,564],{"class":541},[485,1519,567],{"class":560},[485,1521,570],{"class":515},[485,1523,654],{"class":560},[485,1525,1527],{"class":487,"line":1526},38,[485,1528,499],{"emptyLinePlaceholder":498},[485,1530,1532,1534],{"class":487,"line":1531},39,[485,1533,962],{"class":633},[485,1535,1536],{"class":560}," \"\"\n",[485,1538,1540,1542,1544,1547],{"class":487,"line":1539},40,[485,1541,962],{"class":633},[485,1543,561],{"class":560},[485,1545,1546],{"class":541},"🧾 Summary:",[485,1548,788],{"class":560},[485,1550,1552,1554,1556,1559,1562],{"class":487,"line":1551},41,[485,1553,962],{"class":633},[485,1555,561],{"class":560},[485,1557,1558],{"class":541},"    🔗 Duplicates replaced by hardlink: ",[485,1560,1561],{"class":519},"$total_doublons",[485,1563,788],{"class":560},[485,1565,1567,1569,1571,1574,1576,1578,1580,1583,1585,1587,1590,1593,1596,1599],{"class":487,"line":1566},42,[485,1568,962],{"class":633},[485,1570,561],{"class":560},[485,1572,1573],{"class":541},"    💾 Approx. disk space saved: ",[485,1575,1379],{"class":560},[485,1577,1112],{"class":519},[485,1579,1385],{"class":560},[485,1581,1582],{"class":541}," KB (~",[485,1584,1452],{"class":560},[485,1586,1112],{"class":537},[485,1588,1589],{"class":541}," \u002F ",[485,1591,1592],{"class":1460},"1024",[485,1594,1595],{"class":560},"))",[485,1597,1598],{"class":541}," MB)",[485,1600,788],{"class":560},[485,1602,1604,1606,1608,1611],{"class":487,"line":1603},43,[485,1605,962],{"class":633},[485,1607,561],{"class":560},[485,1609,1610],{"class":541},"✅ Done.",[485,1612,788],{"class":560},[391,1614,1615],{},"So, in conclusion, I:",[440,1617,1618,1621,1624,1627],{},[443,1619,1620],{},"Learned many Bash subtleties",[443,1622,1623],{},"Learned never to blindly copy-paste a ChatGPT script without understanding and dry-running it",[443,1625,1626],{},"Learned that Qwen on a RTX 5090 is more coherent than ChatGPT-4o on server farms (not even mentioning “normal” ChatGPT)",[443,1628,1629],{},"Learned that even with 100TB of storage, monitoring it would’ve alerted me much earlier to the 12TB of duplicates lying around",[1631,1632,1633],"style",{},"html pre.shiki code .sDvJj, html code.shiki .sDvJj{--shiki-light:#6A737D;--shiki-light-font-style:inherit;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sAoO4, html code.shiki .sAoO4{--shiki-light:#F97583;--shiki-default:#C792EA;--shiki-dark:#F97583}html pre.shiki code .sJWha, html code.shiki .sJWha{--shiki-light:#79B8FF;--shiki-default:#C3E88D;--shiki-dark:#79B8FF}html pre.shiki code .slcoZ, html code.shiki .slcoZ{--shiki-light:#E1E4E8;--shiki-default:#EEFFFF;--shiki-dark:#E1E4E8}html pre.shiki code .sEgDM, html code.shiki .sEgDM{--shiki-light:#B392F0;--shiki-default:#FFCB6B;--shiki-dark:#B392F0}html pre.shiki code .s11XM, html code.shiki .s11XM{--shiki-light:#9ECBFF;--shiki-default:#C3E88D;--shiki-dark:#9ECBFF}html pre.shiki code .s8K8j, html code.shiki .s8K8j{--shiki-light:#9ECBFF;--shiki-default:#89DDFF;--shiki-dark:#9ECBFF}html pre.shiki code .sJPTy, html code.shiki .sJPTy{--shiki-light:#F97583;--shiki-default:#89DDFF;--shiki-dark:#F97583}html pre.shiki code .s8-mJ, html code.shiki .s8-mJ{--shiki-light:#79B8FF;--shiki-default:#EEFFFF;--shiki-dark:#79B8FF}html pre.shiki code .sJLGa, html code.shiki .sJLGa{--shiki-light:#F97583;--shiki-light-font-style:inherit;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .s8jd1, html code.shiki .s8jd1{--shiki-light:#E1E4E8;--shiki-default:#89DDFF;--shiki-dark:#E1E4E8}html pre.shiki code .sJGgK, html code.shiki .sJGgK{--shiki-light:#79B8FF;--shiki-default:#82AAFF;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .swwWl, html code.shiki .swwWl{--shiki-light:#79B8FF;--shiki-default:#F78C6C;--shiki-dark:#79B8FF}",{"title":481,"searchDepth":495,"depth":495,"links":1635},[],[1637],"Djeex","A bash script to detect and fix duplicate media files in Sonarr and Radarr libraries by replacing copies with hardlinks to reclaim disk space.","md",null,{},{"title":309,"description":1638},"sxaNPC9PikjDgNjAOUbqAPii9xE9rCwLhcehD-zOGdc",[1645,1647],{"title":299,"path":300,"stem":301,"description":1646,"children":-1},"Instameex is a Docker-based tool to merge SDR and HDR photo exports into a proper gain-map JPEG ready for Instagram HDR upload.",{"title":313,"path":314,"stem":315,"description":1648,"children":-1},"A bash script to automatically dump LUKS headers from all encrypted disks, identify them by serial number, and store them in an encrypted archive.",1788645859166]