{"id":29756157,"url":"https://github.com/jbrodriguez/unbalance","last_synced_at":"2026-05-03T01:04:43.765Z","repository":{"id":31395985,"uuid":"34959163","full_name":"jbrodriguez/unbalance","owner":"jbrodriguez","description":"Go/React/Tailwind app to move folders/files between Unraid disks","archived":false,"fork":false,"pushed_at":"2025-07-12T02:31:47.000Z","size":9506,"stargazers_count":210,"open_issues_count":16,"forks_count":16,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-07-24T15:34:40.838Z","etag":null,"topics":["go","react","rsync","tailwind","typescript","unraid"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jbrodriguez.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["jbrodriguez"],"custom":["https://www.paypal.me/jbrodriguezio","https://jbrio.net/unbalanced"]}},"created_at":"2015-05-02T18:43:46.000Z","updated_at":"2025-07-14T02:44:09.000Z","dependencies_parsed_at":"2023-12-11T14:43:19.096Z","dependency_job_id":"fc859016-6840-4142-b615-79fb86edb28b","html_url":"https://github.com/jbrodriguez/unbalance","commit_stats":null,"previous_names":[],"tags_count":116,"template":false,"template_full_name":null,"purl":"pkg:github/jbrodriguez/unbalance","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jbrodriguez%2Funbalance","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jbrodriguez%2Funbalance/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jbrodriguez%2Funbalance/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jbrodriguez%2Funbalance/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jbrodriguez","download_url":"https://codeload.github.com/jbrodriguez/unbalance/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jbrodriguez%2Funbalance/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266886030,"owners_count":24001045,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-24T02:00:09.469Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","react","rsync","tailwind","typescript","unraid"],"created_at":"2025-07-26T16:15:25.382Z","updated_at":"2026-05-03T01:04:43.758Z","avatar_url":"https://github.com/jbrodriguez.png","language":"TypeScript","funding_links":["https://github.com/sponsors/jbrodriguez","https://www.paypal.me/jbrodriguezio","https://jbrio.net/unbalanced"],"categories":[],"sub_categories":[],"readme":"# unbalanced\n\n_tl;dr_ **unbalanced** is an [Unraid](https://unraid.net/) plugin to transfer files/folders between disks in your array.\n\n## Support Fund\n\nIf you wish to do so, read how to [support the developer](https://jbrio.net/unbalanced).\n\n## [Changelog](https://github.com/jbrodriguez/unbalance/releases)\n\n## Screenshot\n\n![Home](meta/images/scatter-select.png)\n\n## Introduction\n\nunbalanced helps you manage space in your Unraid array, via two operating modes:\n\n- **Scatter**\u003cbr/\u003e Transfer data out of a disk, into one or more disks\n\n- **Gather**\u003cbr/\u003e Consolidate data from a user share into a single disk\n\nIt's versatile and can serve multiple purposes, based on your needs.\n\nSome of the use cases are:\n\n- Empty a disk, in order to change filesystems (read\n  [kizer's example](https://forums.unraid.net/topic/43651-plug-in-unbalance/page/2/#comment-431428))\n- Move all seasons of a tv show into a single disk\n- Move a specific folder from a disk to another disk\n- Split your movies/tv shows/games folder from a disk to other disks\n\nYou'll likely come up with other scenarios as you play around with it.\n\n## Core Features\n\n- **Makes sure to fill the target disk(s) as much as possible, without running out of space**\u003cbr\u003e If it can't transfer\n  some files/folders, it will inform you in the console and via notifications (if you set them up in the settings),\n  before any actual transfer takes place.\n\n- **Operates in the background**\u003cbr\u003e You can close your browser while the transfer operation is ongoing. It will keep\n  transferring files on the server and show you the current progress as soon as you reopen the browser.\n\n- **Transfer operations work at the disk level (not at the user share level)**\u003cbr\u003e This avoids file/folder clobbering.\n\n\u003e [!IMPORTANT]\n\u003e IMPORTANT: I suggest giving unbalanced exclusive access to disks (disable mover and/or any dockers that write to disks), so that free space calculation are not affected. If you're only reading data (streaming, etc.), it shouldn't be issue, although the operations may run slower.\n\n## SCATTER Instructions\n\nScatter will transfer data from a source disk into one or more target disks, according to your selection, by filling the target disks, sorted by free space available, as much as possible.\n\n\u003e [!NOTE]\n\u003e Scatter doesn't distribute data evenly across disks. It will fill up the first disk, then the second, and so on.\n\nIt involves the following steps:\n\n**1 - Select** \u003cbr/\u003e\nChoose the source disk, select the files/folders you want to transfer and choose the target disk(s).\n![Select](meta/images/scatter-select.png)\n\n**2 - Plan** \u003cbr/\u003e\nThe logic is:\n\n- Get the contents of the selected files/folders from the source disk\n- Order the target disks by free space available\n- For each target disk, calculate how much it can be filled up with files/folder from the source disk, leaving some\n  headroom (currently set at 1Gb).\n\nAdditionally, it will check files/folders permissions, to warn about potential issues during the transfer stage.\n![Plan](meta/images/scatter-plan.png)\n\n**3 - Transfer** \u003cbr/\u003e You can either MOVE or COPY the files.\n\n- MOVE \u003cbr/\u003e Will first copy the files/folders into the target disk(s), and delete them as soon as the copy is finished.\n\n- COPY \u003cbr/\u003e Will simply transfer the files/folders into the other disk(s).\u003cbr/\u003e **NOTE**: Beware that COPY doesn't\n  delete files/folders on the source disk, so you will be essentially duplicating the data.\n\n~~Internally, all move operations are handled by [diskmv](https://github.com/trinapicot/Unraid-diskmv).~~\n\nInternally, it issues a slight variation of\n[this rsync command](https://forums.unraid.net/topic/35815-re-format-xfs-on-replacement-drive-convert-from-rfs-to-xfs-discussion-only/page/12/#comment-445880).\n\nCheck [this post](https://forums.unraid.net/topic/43651-plug-in-unbalance/page/11/#comment-471957) for additional\ninformation.\n![Transfer](meta/images/scatter-transfer.png)\n\n**4 - Validate (optional)** \u003cbr/\u003e VALIDATE will only be enabled for a SCATTER / COPY operation. Just click the Validate\nbutton in the [History](#history) screen and the operation will be replayed, but with checksum comparisons (instead of\nthe simpler size/modification time check).\n\nWhen using default flags, VALIDATE rsync will be invoked as **-rcvPRX**.\n\n## GATHER Instructions\n\nGATHER will consolidate data from a user share into a single disk.\n\nIt involves the following steps:\n\n**1 - Select**\n\nThe 'Shares' column lets you navigate your user shares, to choose a folder to consolidate\n\nWhen a folder is selected, the current selection and the drives where this folder is located are displayed in the 'Presence' column.\n\nOnce you've chosen the folder, click NEXT.\n![Select](meta/images/gather-select.png)\n\n**2 - Plan**\nThe logic is:\n\n- Find the drives where the folder is located and how much space they occupy\n- Calculate how much data needs to be transferred to each potential target disk\n\nAdditionally, it will check files/folders permissions, to warn about potential issues during the transfer stage.\n\n![Plan](meta/images/gather-plan.png)\n\n**3 - Move** \u003cbr/\u003e\n\nThis page shows which drives have enough space to hold the contents of the folder chosen in the previous step.\n\nThey are shown in descending order by how little data transfer will be required.\n\nA star next to a drive means that the folder is present there.\n\nChoose a target disk, then click Move to start the transfer operation.\n![Transfer](meta/images/gather-transfer.png)\n\n## Installation\n\nThere are 2 ways to install this application\n\n- Apps Tab (Community Application)\u003cbr/\u003e Go to the Apps tab\u003cbr/\u003e Click on the Plugins button (the last one)\u003cbr/\u003e Look for\n  unbalanced\u003cbr/\u003e Click Install\n\n- Plugins Tab (manual)\u003cbr/\u003e Go to the Plugins tab\u003cbr/\u003e Click on Install Plugin\u003cbr/\u003e Paste the following address in the\n  input field: \u003chttps://github.com/jbrodriguez/unbalance/releases/latest/download/unbalanced.plg\u003e\u003cbr/\u003e Click Install\n\n## Running the app\n\nAfter installing the plugin, you can access the web UI, via the following methods:\n\n- Method 1\u003cbr/\u003e Go to Settings \u003e Utilities\u003cbr/\u003e Click on unbalanced\u003cbr/\u003e Click on Open Web UI\u003cbr/\u003e\n\n- Method 2\u003cbr/\u003e Go to Plugins \u003e Installed Plugins\u003cbr/\u003e Click on unbalanced\u003cbr/\u003e Click on Open Web UI\u003cbr/\u003e\n\n- Method 3\u003cbr/\u003e Navigate with your browser to http(s)://Tower:7090/ (replace Tower with the address/name of your Unraid\n  server)\u003cbr/\u003e\n\n## Authentication\n\nWhen authentication is enabled, the first administrator to open the web UI completes a one-time password setup.\n\nPassword requirements:\n\n- Minimum length: 8 characters\n- Maximum length: 256 characters\n- Special characters: allowed\n- Complexity rules: none (no uppercase, number, or symbol requirement)\n\nNew passwords are stored with Argon2id. Existing bcrypt hashes remain supported and are automatically upgraded to Argon2id after the next successful login.\n\n## Other Features\n\n### Transfer\n\nHere you can monitor the progress of an operation. It shows overall metrics, as well as each invididual command as they\nunfold.\n\n![Transfer](meta/images/transfer.png)\n\n### History\n\nunbalanced keeps a history of the operations you have run, showing each command that was executed.\n\nYou can replay the most recent operation (excluding dry-runs) or validate the most recent Scatter Copy.\n\nAdditionally, you can review operations which contain one or more flagged rsync commands.\n\nIf an rsync command has been flagged (applies to Gather and Scatter/Move operations), unbalanced will not delete the source folders/files.\n\nThis allows you to check the issue in detail and take any action deemed necessary.\n\nOnce you've done that, you can delete the source folders/files through the UI, if you want.\n\n![History](meta/images/history.png)\n\n### Settings\n\nThese are pretty much straigthforward.\n\nA word of caution with the custom rsync flags: it's for **power users** only.\n\nunbalanced is optimized to work with the default flags, you must be VERY knowledgeable in rsync if you want to add any\nflag.\n\n![Settings](meta/images/settings.png)\n\n### Log\n\n![Log](meta/images/log.png)\n\n## Videos\n\n\u003e NOTE: this refers to an older version of unbalanced, but the concepts are the same.\n\nThanks to gridrunner (Unraid forum member), you can watch unbalanced in action !\n\n[Must Have Unraid Plugins - Part 3 Disk Utility Plugins](https://www.youtube.com/watch?v=Wz4-YlH1lTk)\n\nThe discussion specific to unbalanced starts [here](https://youtu.be/Wz4-YlH1lTk?t=859).\n\n## Credits\n\n~~This app uses the [diskmv](https://github.com/trinapicot/unraid-diskmv) script (check the\n[forum thread](https://forums.unraid.net/topic/34547-diskmv-a-set-of-utilities-to-move-files-between-disks/) for additional information).~~\n\nThe icon was graciously created by\n[hernandito](https://forums.unraid.net/topic/38028-docker-unbalance/#comment-368452) (fellow Unraid forums member)\n\nIt was built with:\n\n- [Go](https://golang.org/) - Back End\n- [echo](https://github.com/labstack/echo) - REST and websocket api\n- [pubsub](https://github.com/cskr/pubsub) - Pub/Sub implementation\n- [React](https://facebook.github.io/react/) - Front End\n- [zustand](https://github.com/pmndrs/zustand) - Flux/Redux-like React framework\n- [tailwind](https://tailwindcss.com) - Css framework\n- [vite](https://vitejs.dev) - Tooling\n\n## Development environment\n\n- setup go development environment\n- setup node development environment\n- clone repository\n- make release on root folder will create unbalanced binary (with embedded website)\n- transfer binary to unraid server\n- run unbalanced on the command line (do a ps aux | grep unbalanced first, to check how to invoke it)\n- (optional) if you want to do some ui debugging, set up a proxy on vite.config.ts\n\n### original\n\n```js\nimport { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\nimport tsconfigPaths from \"vite-tsconfig-paths\";\nimport path from \"path\";\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [react(), tsconfigPaths()],\n  resolve: {\n    alias: {\n      \"@\": path.resolve(__dirname, \"./src\"),\n    },\n  },\n});\n```\n\n### modified\n\n```js\nimport { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\nimport tsconfigPaths from \"vite-tsconfig-paths\";\nimport path from \"path\";\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [react(), tsconfigPaths()],\n  resolve: {\n    alias: {\n      \"@\": path.resolve(__dirname, \"./src\"),\n    },\n  },\n  server: {\n    proxy: {\n      \"/api\": {\n        target: \"http(s)://\u003cunraid-server\u003e:7090\",\n      },\n    },\n  },\n});\n```\n\nthen run `npm run dev` and point your browser to the endpoint returned by this command (generally \u003chttp://localhost:5173\u003e)\n\n## Activity\n\n![Alt](https://repobeats.axiom.co/api/embed/c5745d8699df25ff4e087e691f104aeeda2bd17b.svg \"Repobeats analytics image\")\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjbrodriguez%2Funbalance","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjbrodriguez%2Funbalance","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjbrodriguez%2Funbalance/lists"}