{"id":21039331,"url":"https://github.com/clsty/butter-snap","last_synced_at":"2025-07-20T17:32:37.796Z","repository":{"id":242545442,"uuid":"809852385","full_name":"clsty/butter-snap","owner":"clsty","description":"A Bash script for automating Btrfs snapshots","archived":false,"fork":false,"pushed_at":"2024-06-04T23:13:39.000Z","size":37,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-13T21:18:05.771Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/clsty.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2024-06-03T15:13:36.000Z","updated_at":"2025-02-22T19:50:39.000Z","dependencies_parsed_at":"2024-06-03T17:46:57.948Z","dependency_job_id":"c0a898f6-0580-4e26-b23f-3c604599913b","html_url":"https://github.com/clsty/butter-snap","commit_stats":null,"previous_names":["clsty/butter-snap"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/clsty/butter-snap","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clsty%2Fbutter-snap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clsty%2Fbutter-snap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clsty%2Fbutter-snap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clsty%2Fbutter-snap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/clsty","download_url":"https://codeload.github.com/clsty/butter-snap/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clsty%2Fbutter-snap/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266165538,"owners_count":23886636,"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","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":[],"created_at":"2024-11-19T13:39:01.854Z","updated_at":"2025-07-20T17:32:37.777Z","avatar_url":"https://github.com/clsty.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Butter Snap\nA Bash script to create and maintain the history of snapshots of Btrfs (sub)volumes.\n\n\u003e Butter is from the \"Btr\" string in name \"Btrfs\", despite that it's actually \"B-tree FS\", not \"Butter FS\". Snap is for snapshot.\n\nFeatures:\n- Able to specify the path to store the snapshots.\n  - Can be inside or outside the target.\n- Able to purge old snapshots when too many exist.\n- Able to keep multiple snapshot schedules for the same target.\n- Designed to be called from cron on a regular schedule.\n\n## Requirements\n- System: normally a GNU/Linux Distro.\n- Dependencies:\n  - Bash.\n  - btrfs-progs, which provides `btrfs` command.\n\n## Install\n- AUR: `yay -S --needed --noconfirm butter-snap-git`\n- Manually: Clone the repo, copy `buttersnap` to `/usr/local/bin/` (or elsewhere included in `$PATH`) and ensure it has executing permission.\n\n## Basic usage\nSyntax:\n```bash\n# Options can be placed before target.\nbuttersnap \u003ctarget\u003e [options]\n```\nThe command above creates a snapshot of `\u003ctarget\u003e` as `\u003cstore path\u003e/\u003csnapname\u003e`.\n- `\u003ctarget\u003e`: The path or mountpoint of a Btrfs (sub)volume.\n  - Internally it will be read as `target=$(realpath -m \u003ctarget\u003e)`.\n\n\u003e Example: `buttersnap / -n\"hourly\"` will make a snapshot in `/.snapshots` with a name `hourly_\u003cdate\u003e_\u003ctime\u003e`.\n\u003e - `\u003cdate\u003e` is on the form `YYYY-MM-DD`,\n\u003e - `\u003ctime\u003e` is on the form `HH:MM:SS`,\n\u003e - The 5 newest snapshots matching the prefix `hourly_` are kept around; the rest are deleted.\n\n\n**Options for `\u003cstore path\u003e`:**\n- `-s`, `--store-dir \u003cstore directory\u003e`: Specify the value for `\u003cstore directory\u003e` (by default `.snapshots`).\n- `-S`, `--store-pathtype \u003cstore pathtype\u003e`: Specify the value for `\u003cstore pathtype\u003e` (by default `rel`).\n  - `rel` (relative): Let `\u003cstore path\u003e` to be `\u003ctarget (in realpath)\u003e/\u003cstore directory\u003e`.\n  - `mim` (mimic):    Let `\u003cstore path\u003e` to be `\u003cstore directory\u003e/\u003ctarget (in realpath)\u003e`.\n  - `abs` (absolute): Let `\u003cstore path\u003e` to be `\u003cstore directory\u003e`.\n    - In this case, choose `\u003csnapname adj\u003e` wisely to avoid name conflicts.\n\n**Options for `\u003csnapname\u003e`:**\n- `-n`, `--snapname-adj \u003csnapname adj\u003e`: To be used in the name of the snapshot, by default as prefix. The default value is `snapshot`.\n  - It's recommended to set this value corresponding to the schedule, such as `hourly`, `daily`, `weekly` or `1m`, `3h`, `1d`, `1w`, `3mo`.\n- `-N`,`--snapname-type \u003csnapname type\u003e`: Select a set of snapname and matching pattern. By default `default`.\n  - `default`: Snapname in form of `\u003csnapname adj\u003e_%Y-%m-%d_%H:%M:%S`, with corresponding matching pattern.\n    - Applicable snapname option(s): `compatible`, `postfix`.\n  - `vfs`: Use the Samba `vfs_shadow_copy` snapshot naming convention. Snapname in form of `@GMT-%Y.%m.%d-%H.%M.%S`, with corresponding matching pattern.\n  - `custom`: Custom snapname and matching pattern.\n    - `--snapname-value \u003csnapname\u003e`: Specify customed snapname.\n    - `--snapname-pattern \u003csnapname pattern\u003e`: Specify customed pattern to match the snapname.\n- `-o`,`--snapname-ops \u003csnapname options\u003e`: Additional options for a snapname type. By default none.\n  - Only apply when applicable.\n  - Multiple options should be split by `,`, e.g. `compatible,postfix`.\n  - `compatible`: Compatible snapshot names (i.e. no colons that confuse SAMBA/Windows clients).\n  - `postfix`: Use `\u003csnapname adj\u003e` as postfix instead of prefix. Might be usefull for chronological sorting.\n\n**Options for creating behavior:**\n- `-t`, `--time \u003ctime\u003e`: A snapshot will be created **only** if the newest already existing snapshot is older than `\u003ctime\u003e` in seconds.\n  - Unless `-T` is specified, no snapshot will be made if `\u003ctarget\u003e` has identical timestamp as the newest snapshot. The modification timestamps of the subvolumes/folders are used for comparison which **might not** work in some scenarios.\n- `-T`, `--use-transid`: When `-t` is specified, no snapshot will be made if `\u003ctarget\u003e` has a lower or equal transition-id than newest snapshot.\n- `-r`, `--readonly`: Create the snapshot as readonly (requires btrfs-tools \u003e v0.20).\n- `-E`, `--no-omit`: Treats omitting of snapshots (e.g. due to options `-t`/`-T`) as an error.\n\n**Options for auto-clean behavior:**\n- `-k`, `--keep \u003cnumber\u003e`: Sort the snapshots matching `\u003csnapname pattern\u003e` by using `ls -dr` and keep the first `\u003cnumber\u003e` snapshots; the rest ones will be deleted.\n  - 5 snapshots will be kept if this option is not specified.\n\n**Other options:**\n- `-q`, `--quiet`: Silent unless an error occurs. Such output is cron-compatible.\n- `-h`, `--help`: Print help message and exit.\n- `-V`, `--version`: Print version message and exit.\n- `--show-all-btrfs`: Print current Btrfs mountpoints and unmounted Btrfs subvolumes in system.\n\n## Cron usage\nChoose only one method below will be enough.\n\n### Method: crontab\nSuppose you have two Btrfs subvolumes mounted at `/` and `/home`.\n\nIn crontab, add these two lines:\n```cron\n*/5   *   *   *   *   buttersnap /     -n5m -k12 -r\n0     0   *   *   *   buttersnap /home -n1d -k7  -r -S\"mim\" -s\"/snapshots\"\n```\n\nThe above cronjob will\n- Every 5 minutes, create a read-only snapshot of `/` with name prefix `5m_` keeping 12 generations in `/.snapshots`.\n- Every day, create a read-only snapshot of `/home` with name prefix `1d_` keeping 7 generations in `/snapshots/home`.\n\n### Method: polling\nSuppose you have a Btrfs subvolume mounted at `/data`.\n\nFind a way to run the commands below regularily (e.g. every 10 minutes).\n```cron\nbuttersnap -r -S\"abs\" -s \u003cstore path\u003e -t3600           /data -n\"data_hourly\" -k24\nbuttersnap -r -S\"abs\" -s \u003cstore path\u003e -t$((3600*24))   /data -n\"data_daily\"  -k7\nbuttersnap -r -S\"abs\" -s \u003cstore path\u003e -t$((3600*24*7)) /data -n\"data_weekly\" -k4\n```\n\n## License\nThis program is distributed under the [GNU General Public License](http://www.gnu.org/licenses/gpl.txt).\n\n## History\nThe script is originally a rework of [QDaniel/btrfs-snap](https://github.com/QDaniel/btrfs-snap), which is a fork of [jf647/btrfs-snap](https://github.com/jf647/btrfs-snap).\n\n### Butter Snap\n- Developed by [clsty](https://github.com/clsty).\n\n### btrfs-snap\n- Originally by Birger Monsen \u003cbirger@birger.sh\u003e\n- Readonly and basedir additions by James FitzGibbon \u003cjames@nadt.net\u003e\n- VFS snapshot naming support by gitmopp (https://github.com/gitmopp)\n- Support for snapshotting unmounted btrfs subvolumes by Brian Kloppenborg (https://github.com/bkloppenborg)\n- Add switches `-c` (for windows-combitible timestamps) and `-d` (for specifying the snapshot directory) by Lukas Pirl (btrfs-snap@lukas-pirl.de)\n- Add switches `-B` (absolute path of snapshot directory) and `-t`/`-T` (time-dependent snapshot) by Michael Walz (btrfs-snap@serpedon.de)\n- Other improvements by [chipturner](https://github.com/chipturner), [lpirl](https://github.com/lpirl) and [QDaniel](https://github.com/QDaniel)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclsty%2Fbutter-snap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclsty%2Fbutter-snap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclsty%2Fbutter-snap/lists"}