-
-
Notifications
You must be signed in to change notification settings - Fork 867
copy: copy an archive to a new archive name, #2300 #10221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
ThomasWaldmann
merged 2 commits into
borgbackup:master
from
ThomasWaldmann:archive-copy-2300
Aug 28, 2026
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| .\" Man page generated from reStructuredText | ||
| .\" by the Docutils 0.22.4 manpage writer. | ||
| . | ||
| . | ||
| .nr rst2man-indent-level 0 | ||
| . | ||
| .de1 rstReportMargin | ||
| \\$1 \\n[an-margin] | ||
| level \\n[rst2man-indent-level] | ||
| level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] | ||
| - | ||
| \\n[rst2man-indent0] | ||
| \\n[rst2man-indent1] | ||
| \\n[rst2man-indent2] | ||
| .. | ||
| .de1 INDENT | ||
| .\" .rstReportMargin pre: | ||
| . RS \\$1 | ||
| . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] | ||
| . nr rst2man-indent-level +1 | ||
| .\" .rstReportMargin post: | ||
| .. | ||
| .de UNINDENT | ||
| . RE | ||
| .\" indent \\n[an-margin] | ||
| .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] | ||
| .nr rst2man-indent-level -1 | ||
| .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] | ||
| .in \\n[rst2man-indent\\n[rst2man-indent-level]]u | ||
| .. | ||
| .TH "borg-copy" "1" "2026-08-28" "" "borg backup tool" | ||
| .SH Name | ||
| borg-copy \- Copy an archive to a new archive name. | ||
| .SH SYNOPSIS | ||
| .sp | ||
| borg [common options] copy [options] OLDNAME NEWNAME | ||
| .SH DESCRIPTION | ||
| .sp | ||
| This command copies an existing archive to a new archive with a different name, | ||
| keeping the existing archive. | ||
| .sp | ||
| Afterwards, the repository has two archives with the same contents, but with | ||
| different names and different archive IDs. The copy is an independent archive: | ||
| deleting either of the two archives keeps the other one intact, because | ||
| \fBborg compact\fP only frees chunks that no remaining archive references. | ||
| .sp | ||
| Copying is cheap and fast: no file content is read or written, only a new archive | ||
| metadata object is created. Like any deduplicated archives, the two archives share | ||
| their data, so a copy needs almost no additional repository space. | ||
| .sp | ||
| Because archive names do not need to be unique, NEWNAME may also be the name of | ||
| some \fIother\fP already existing archive \- the copy then just becomes another archive | ||
| of that archive series. | ||
| .sp | ||
| NEWNAME must be different from the name of the archive that is copied, though: the | ||
| copy would get identical metadata and thus the same archive ID as its source, so no | ||
| second archive could be created. | ||
| .sp | ||
| OLDNAME must match precisely one archive: give an archive name (if it is unique) or | ||
| an archive ID, like \fBaid:d34db33f\fP\&. | ||
| .sp | ||
| Note: to copy archives into a \fIdifferent\fP repository, use \fBborg transfer\fP\&. | ||
| .SH OPTIONS | ||
| .sp | ||
| See \fIborg\-common(1)\fP for common options of Borg commands. | ||
| .SS arguments | ||
| .INDENT 0.0 | ||
| .TP | ||
| .B OLDNAME | ||
| specify the existing archive name or ID | ||
| .TP | ||
| .B NEWNAME | ||
| specify the new archive name | ||
| .UNINDENT | ||
| .SH EXAMPLES | ||
| .INDENT 0.0 | ||
| .INDENT 3.5 | ||
| .sp | ||
| .EX | ||
| # create an archive, then keep a copy of it under a stable name: | ||
| $ borg create backup\-2016\-02\-15 ~ | ||
| $ borg copy backup\-2016\-02\-15 known\-good | ||
| $ borg repo\-list | ||
| e6a2b1c4 Mon, 2016\-02\-15 19:50:19 +0100 backup\-2016\-02\-15 tw MacBook\-Pro | ||
| 9f3d0a77 Mon, 2016\-02\-15 19:50:19 +0100 known\-good tw MacBook\-Pro | ||
|
|
||
| # the copy is an independent archive: | ||
| # after deleting (and compacting away) the original, the copy is still complete. | ||
| $ borg delete backup\-2016\-02\-15 | ||
| $ borg compact | ||
| $ borg extract known\-good | ||
|
|
||
| # if the archive name is not unique, address the archive by its ID: | ||
| $ borg copy aid:e6a2b1c4 known\-good | ||
| .EE | ||
| .UNINDENT | ||
| .UNINDENT | ||
| .SH SEE ALSO | ||
| .sp | ||
| \fIborg\-common(1)\fP | ||
| .SH Author | ||
| The Borg Collective | ||
| .\" End of generated man page. |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -55,6 +55,7 @@ Usage | |
| usage/find | ||
| usage/tag | ||
| usage/rename | ||
| usage/copy | ||
| usage/diff | ||
| usage/delete | ||
| usage/prune | ||
|
|
||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| .. include:: copy.rst.inc | ||
|
|
||
| Examples | ||
| ~~~~~~~~ | ||
| :: | ||
|
|
||
| # create an archive, then keep a copy of it under a stable name: | ||
| $ borg create backup-2016-02-15 ~ | ||
| $ borg copy backup-2016-02-15 known-good | ||
| $ borg repo-list | ||
| e6a2b1c4 Mon, 2016-02-15 19:50:19 +0100 backup-2016-02-15 tw MacBook-Pro | ||
| 9f3d0a77 Mon, 2016-02-15 19:50:19 +0100 known-good tw MacBook-Pro | ||
|
|
||
| # the copy is an independent archive: | ||
| # after deleting (and compacting away) the original, the copy is still complete. | ||
| $ borg delete backup-2016-02-15 | ||
| $ borg compact | ||
| $ borg extract known-good | ||
|
|
||
| # if the archive name is not unique, address the archive by its ID: | ||
| $ borg copy aid:e6a2b1c4 known-good |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| .. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit! | ||
|
|
||
| .. _borg_copy: | ||
|
|
||
| borg copy | ||
| --------- | ||
| .. code-block:: none | ||
|
|
||
| borg [common options] copy [options] OLDNAME NEWNAME | ||
|
|
||
| .. only:: html | ||
|
|
||
| .. class:: borg-options-table | ||
|
|
||
| +-------------------------------------------------------+-------------+-----------------------------------------+ | ||
| | **positional arguments** | | ||
| +-------------------------------------------------------+-------------+-----------------------------------------+ | ||
| | | ``OLDNAME`` | specify the existing archive name or ID | | ||
| +-------------------------------------------------------+-------------+-----------------------------------------+ | ||
| | | ``NEWNAME`` | specify the new archive name | | ||
| +-------------------------------------------------------+-------------+-----------------------------------------+ | ||
| | .. class:: borg-common-opt-ref | | ||
| | | | ||
| | :ref:`common_options` | | ||
| +-------------------------------------------------------+-------------+-----------------------------------------+ | ||
|
|
||
| .. raw:: html | ||
|
|
||
| <script type='text/javascript'> | ||
| $(document).ready(function () { | ||
| $('.borg-options-table colgroup').remove(); | ||
| }) | ||
| </script> | ||
|
|
||
| .. only:: latex | ||
|
|
||
| OLDNAME | ||
| specify the existing archive name or ID | ||
| NEWNAME | ||
| specify the new archive name | ||
|
|
||
|
|
||
| :ref:`common_options` | ||
| | | ||
|
|
||
| Description | ||
| ~~~~~~~~~~~ | ||
|
|
||
| This command copies an existing archive to a new archive with a different name, | ||
| keeping the existing archive. | ||
|
|
||
| Afterwards, the repository has two archives with the same contents, but with | ||
| different names and different archive IDs. The copy is an independent archive: | ||
| deleting either of the two archives keeps the other one intact, because | ||
| ``borg compact`` only frees chunks that no remaining archive references. | ||
|
|
||
| Copying is cheap and fast: no file content is read or written, only a new archive | ||
| metadata object is created. Like any deduplicated archives, the two archives share | ||
| their data, so a copy needs almost no additional repository space. | ||
|
|
||
| Because archive names do not need to be unique, NEWNAME may also be the name of | ||
| some *other* already existing archive - the copy then just becomes another archive | ||
| of that archive series. | ||
|
|
||
| NEWNAME must be different from the name of the archive that is copied, though: the | ||
| copy would get identical metadata and thus the same archive ID as its source, so no | ||
| second archive could be created. | ||
|
|
||
| OLDNAME must match precisely one archive: give an archive name (if it is unique) or | ||
| an archive ID, like ``aid:d34db33f``. | ||
|
|
||
| Note: to copy archives into a *different* repository, use ``borg transfer``. |
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| from ._common import with_repository, with_archive | ||
| from ..constants import * # NOQA | ||
| from ..helpers import archivename_validator, bin_to_hex | ||
| from ..helpers.argparsing import ArgumentParser | ||
| from ..manifest import Manifest | ||
|
|
||
| from ..logger import create_logger | ||
|
|
||
| logger = create_logger() | ||
|
|
||
|
|
||
| class CopyMixIn: | ||
| @with_repository(cache=True, compatibility=(Manifest.Operation.CHECK,)) | ||
| @with_archive | ||
| def do_copy(self, args, repository, manifest, cache, archive): | ||
| """Copy an archive to a new archive name.""" | ||
| old_id = archive.id | ||
| archive.copy(args.newname) | ||
| manifest.write() | ||
| logger.info(f"id: {bin_to_hex(old_id):.8} -> {bin_to_hex(archive.id):.8}, name: {archive.name}.") | ||
|
|
||
| def build_parser_copy(self, subparsers, common_parser, mid_common_parser): | ||
| from ._common import process_epilog | ||
|
|
||
| copy_epilog = process_epilog( | ||
| """ | ||
| This command copies an existing archive to a new archive with a different name, | ||
| keeping the existing archive. | ||
|
|
||
| Afterwards, the repository has two archives with the same contents, but with | ||
| different names and different archive IDs. The copy is an independent archive: | ||
| deleting either of the two archives keeps the other one intact, because | ||
| ``borg compact`` only frees chunks that no remaining archive references. | ||
|
|
||
| Copying is cheap and fast: no file content is read or written, only a new archive | ||
| metadata object is created. Like any deduplicated archives, the two archives share | ||
| their data, so a copy needs almost no additional repository space. | ||
|
|
||
| Because archive names do not need to be unique, NEWNAME may also be the name of | ||
| some *other* already existing archive - the copy then just becomes another archive | ||
| of that archive series. | ||
|
|
||
| NEWNAME must be different from the name of the archive that is copied, though: the | ||
| copy would get identical metadata and thus the same archive ID as its source, so no | ||
| second archive could be created. | ||
|
|
||
| OLDNAME must match precisely one archive: give an archive name (if it is unique) or | ||
| an archive ID, like ``aid:d34db33f``. | ||
|
|
||
| Note: to copy archives into a *different* repository, use ``borg transfer``. | ||
| """ | ||
| ) | ||
| subparser = ArgumentParser(parents=[common_parser], description=self.do_copy.__doc__, epilog=copy_epilog) | ||
| subparsers.add_subcommand("copy", subparser, help="copy an archive to a new archive name") | ||
| subparser.add_argument( | ||
| "name", metavar="OLDNAME", type=archivename_validator, help="specify the existing archive name or ID" | ||
| ) | ||
| subparser.add_argument( | ||
| "newname", metavar="NEWNAME", type=archivename_validator, help="specify the new archive name" | ||
| ) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.