borg-create(1)
π borg-create(1) β Create new archive π
okay bestie, welcome to borg-create(1), the part of the borg backup tool where you literally make a whole new archive. it's giving main character energy and it's honestly iconic. let's go π¦
β¨ SYNOPSIS β¨
borg [common options] create [options] ARCHIVE [PATH...]
πΈ DESCRIPTION πΈ
so this command? it creates a backup archive containing, like, every single file it finds while recursively traversing all the paths you gave it. paths get added to the archive as they are given, which means if you want relative paths, you literally have to run the command from the correct directory. no cap. π
the slashdot hack (aka recursion roots) is triggered by using /./:
/this/gets/stripped/./this/gets/archived
means "process that filesystem object, but strip the prefix on the left side of ./ from the archived items" β so in this case, this/gets/archived will be the path in the archived item. slay. π
when you give '-' as a path, Borg will read data from standard input and create a file 'stdin' in the created archive from that data. in some cases it's more appropriate to use --content-from-command. (see the "Reading from stdin" section below for details π)
the archive will consume almost no disk space for files or parts of files that have already been stored in other archives. it's giving deduplication royalty π
the archive name needs to be unique. it must not end in '.checkpoint' or '.checkpoint.N' (with N being a number), because these names are used for checkpoints and treated in special ways. don't do it. periodt.
in the archive name, you may use the following placeholders: {now}, {utcnow}, {fqdn}, {hostname}, {user} and some others. β¨
backup speed is increased by not reprocessing files that are already part of existing archives and weren't modified. the detection of unmodified files is done by comparing multiple file metadata values with previous values kept in the files cache.
this comparison can operate in different modes as given by --files-cache:
ctime,size,inode(default)mtime,size,inode(default behavior of borg versions older than1.1.0rc4)ctime,size(ignore the inode number)mtime,size(ignore the inode number)rechunk,ctime(all files are considered modified - rechunk, cache ctime)rechunk,mtime(all files are considered modified - rechunk, cache mtime)disabled(disable the files cache, all files considered modified - rechunk)
π inode number: better safety, but often unstable on network file systems
normally, detecting file modifications will take inode information into consideration to improve the reliability of file change detection. π this is problematic for files located on SSHFS and similar network file systems which do not provide stable inode numbers; such files will always be considered modified. you can use modes without inode in this case to improve performance, but the reliability of change detection might be reduced. trade-offs, bestie π
π ctime vs. mtime: safety vs. speed
- ctime is a rather safe way to detect changes to a file (metadata and contents) as it cannot be set from user space. however, a metadata-only change will already update the ctime, so there might be some unnecessary chunking/hashing even without content changes. some file systems do not support ctime (change time). for example, doing a
chownorchmodto a file will change its ctime. - mtime usually works and only updates if file contents were changed. but mtime can be arbitrarily set from user space, e.g., to set mtime back to the same value it had before a content change happened. this can be used maliciously as well as well-meant, but in both cases mtime-based cache modes can be problematic. π
the --files-changed option controls how Borg detects if a file has changed during backup:
ctime(default): use ctime to detect changes. this is the safest option.mtime: use mtime to detect changes.disabled: disable the "file has changed while we backed it up" detection completely. this is not recommended unless you know what you're doing, as it could lead to inconsistent backups if files change during the backup process.
the mount points of file systems or file system snapshots should be the same for every creation of a new archive to ensure fast operation. this is because the file cache that is used to determine changed files quickly uses absolute file names. if this is not possible, consider creating a bind mount to a stable location. π«Ά
the --progress option shows (from left to right) Original, Compressed and Deduplicated (O, C and D, respectively), then the number of files (N) processed so far, followed by the currently processed path. it's giving dashboard π
when using --stats, you will get some statistics about how much data was added β the "This Archive" deduplicated size there is most interesting as that is how much your repository will grow. please note that the "All archives" stats refer to the state after creation. --stats can be slow β if you want something faster, use --quick-stats (this skips the repository-wide "All archives" and chunk index statistics). the --stats / --quick-stats and --dry-run options are mutually exclusive because the data is not actually compressed and deduplicated during a dry run. π₯
for more help on include/exclude patterns, see the borg_patterns command output.
for more help on placeholders, see the borg_placeholders command output.
π OPTIONS π
see borg-common(1) for common options of Borg commands.
arguments
ARCHIVEβ name of archive to create (must be also a valid directory name)PATHβ paths to archive
options
-n,--dry-runβ do not create a backup archive-s,--statsβ print statistics for the created archive--quick-statsβ print only archive statistics, skipping repository-wide statistics--listβ output verbose list of items (files, dirs, ...)--filter STATUSCHARSβ only display items with the given status characters (see description)--jsonβ output stats as JSON. Implies--stats.--no-cache-syncβ experimental: do not synchronize the cache. Implies not using the files cache.--stdin-name NAMEβ useNAMEin archive for stdin data (default:'stdin')--stdin-user USERβ set userUSERin archive for stdin data (default:'root')--stdin-group GROUPβ set groupGROUPin archive for stdin data (default:'wheel')--stdin-mode Mβ set mode toMin archive for stdin data (default:0660)--content-from-commandβ interpretPATHas command and store its stdout. See also section "Reading from stdin" below.--paths-from-stdinβ read DELIM-separated list of paths to backup from stdin. All control is external: it will back up all files given - no more, no less.--paths-from-commandβ interpretPATHas command and treat its output as--paths-from-stdin--paths-delimiter DELIMβ set path delimiter for--paths-from-stdinand--paths-from-command(default:\n)
π Include/Exclude options π
-e PATTERN,--exclude PATTERNβ exclude paths matchingPATTERN--exclude-from EXCLUDEFILEβ read exclude patterns fromEXCLUDEFILE, one per line--pattern PATTERNβ include/exclude paths matchingPATTERN--patterns-from PATTERNFILEβ read include/exclude patterns fromPATTERNFILE, one per line--exclude-cachesβ exclude directories that contain aCACHEDIR.TAGfile (<http://www.bford.info/cachedir/spec.html>)--exclude-if-present NAMEβ exclude directories that are tagged by containing a filesystem object with the givenNAME--keep-exclude-tagsβ if tag objects are specified with--exclude-if-present, don't omit the tag objects themselves from the backup archive--exclude-nodumpβ exclude files flaggedNODUMP--exclude-datalessβ exclude files flaggedDATALESS(macOS: placeholder files whose content is not materialized locally, e.g. not-downloaded cloud storage files)
π¦ Filesystem options π¦
-x,--one-file-systemβ stay in the same file system and do not store mount points of other file systems - this might behave different from your expectations, see the description below.--numeric-ownerβ deprecated, use--numeric-idsinstead--numeric-idsβ only store numeric user and group identifiers--noatimeβ do not store atime into archive--atimeβ do store atime into archive--noctimeβ do not store ctime into archive--nobirthtimeβ do not store birthtime (creation date) into archive--nobsdflagsβ deprecated, use--noflagsinstead--noflagsβ do not read and store flags (e.g.NODUMP,IMMUTABLE) into archive--noaclsβ do not read and store ACLs into archive--noxattrsβ do not read and store xattrs into archive--sparseβ detect sparse holes in input (supported only by fixed chunker)--files-cache MODEβ operate files cache inMODE. default:ctime,size,inode--files-changed MODEβ specify how to detect if a file has changed during backup (ctime,mtime,disabled). default:ctime--read-specialβ open and read block and char device files as well as FIFOs as if they were regular files. Also follows symlinks pointing to these kinds of files.
π Archive options π
--comment COMMENTβ add a comment text to the archive--timestamp TIMESTAMPβ manually specify the archive creation date/time (UTC,yyyy-mm-ddThh:mm:ssformat). Alternatively, give a reference file/directory.-c SECONDS,--checkpoint-interval SECONDSβ write checkpoint everySECONDSseconds (Default:1800)--chunker-params PARAMSβ specify the chunker parameters (ALGO,CHUNK_MIN_EXP,CHUNK_MAX_EXP,HASH_MASK_BITS,HASH_WINDOW_SIZE). default:buzhash,19,23,21,4095-C COMPRESSION,--compression COMPRESSIONβ select compression algorithm, see the output of theborg help compressioncommand for details.
β¨ EXAMPLES β¨
okay bestie, this is the part where it all clicks. real commands, real vibes, copy-paste energy π«Ά
the classic: back up a folder into a named archive
# Backup ~/Documents into an archive named "my-documents"
$ borg create /path/to/repo::my-documents ~/Documents
same thing but let me WATCH it happen
# same, but list all files as we process them
$ borg create --list /path/to/repo::my-documents ~/Documents
the slashdot hack β strip the path prefix so your archive isn't giving /mnt/disk/docs energy
# Backup /mnt/disk/docs, but strip path prefix using the slashdot hack
$ borg create /path/to/repo::docs /mnt/disk/./docs
two folders, one archive, and we're saying bye to the .pyc files
# Backup ~/Documents and ~/src but exclude pyc files
$ borg create /path/to/repo::my-files \
~/Documents \
~/src \
--exclude '*.pyc'
excluding thumbnails but ONLY the shallow ones, don't get it twisted
# Backup home directories excluding image thumbnails (i.e. only
# /home/<one directory>/.thumbnails is excluded, not /home/*/*/.thumbnails etc.)
$ borg create /path/to/repo::my-files /home \
--exclude 'sh:home/*/.thumbnails'
root filesystem backup, dated name, zlib compression. heads up: zlib is good but slow, the default is lz4 which is fast with a low compression ratio
# Backup the root filesystem into an archive named "root-YYYY-MM-DD"
# use zlib compression (good, but slow) - default is lz4 (fast, low compression ratio)
$ borg create -C zlib,6 --one-file-system /path/to/repo::root-{now:%Y-%m-%d} /
"push" style β remote host, port 2222, logging in as user borg π
# Backup onto a remote host ("push" style) via ssh to port 2222,
# logging in as user "borg" and storing into /path/to/repo
$ borg create ssh://borg@backup.example.org:2222/path/to/repo::{fqdn}-root-{now} /
"pull" style β you mount the remote with sshfs and back it up locally. look at the pipeline, it eats
# Backup a remote host locally ("pull" style) using sshfs
$ mkdir sshfs-mount
$ sshfs root@example.com:/ sshfs-mount
$ cd sshfs-mount
$ borg create /path/to/repo::example.com-root-{now:%Y-%m-%d} .
$ cd ..
$ fusermount -u sshfs-mount
going feral for deduplication. this is a BIG effort β big chunk management overhead, needs a lot of RAM and disk space, see the formula in the internals docs. these params are the same as borg < 1.0 or attic:
# Make a big effort in fine granular deduplication (big chunk management
# overhead, needs a lot of RAM and disk space, see formula in internals
# docs - same parameters as borg < 1.0 or attic):
$ borg create --chunker-params buzhash,10,23,16,4095 /path/to/repo::small /smallstuff
raw devices β and bestie, this one comes with a WARNING: it must not be active, in use, or mounted at that time
# Backup a raw device (must not be active/in use/mounted at that time)
$ borg create --read-special --chunker-params fixed,4194304 /path/to/repo::my-sdx /dev/sdX
sparse disk image β same warning applies, must not be active/in use/mounted
# Backup a sparse disk image (must not be active/in use/mounted at that time)
$ borg create --sparse --chunker-params fixed,4194304 /path/to/repo::my-disk my-disk.raw
now the compression buffet, pick your fighter π₯
no compression at all, none:
# No compression (none)
$ borg create --compression none /path/to/repo::arch ~
super fast, low compression β this is lz4, and it's the default:
# Super fast, low compression (lz4, default)
$ borg create /path/to/repo::arch ~
less fast, higher compression, where N is 0..9:
# Less fast, higher compression (zlib, N = 0..9)
$ borg create --compression zlib,N /path/to/repo::arch ~
even slower, even higher compression, again N is 0..9:
# Even slower, even higher compression (lzma, N = 0..9)
$ borg create --compression lzma,N /path/to/repo::arch ~
only squeeze the stuff that's actually squeezeable, N = 0..9:
# Only compress compressible data with lzma,N (N = 0..9)
$ borg create --compression auto,lzma,N /path/to/repo::arch ~
archive name placeholders, the moment everyone's been waiting for πΈ
# Use short hostname, user name and current time in archive name
$ borg create /path/to/repo::{hostname}-{user}-{now} ~
# Similar, use the same datetime format that is default as of borg 1.1
$ borg create /path/to/repo::{hostname}-{user}-{now:%Y-%m-%dT%H:%M:%S} ~
# As above, but add nanoseconds
$ borg create /path/to/repo::{hostname}-{user}-{now:%Y-%m-%dT%H:%M:%S.%f} ~
relative paths? just cd into the right spot first, it's giving main character problem-solving
# Backing up relative paths by moving into the correct directory first
$ cd /home/user/Documents
# The root directory of the archive will be "projectA"
$ borg create /path/to/repo::daily-projectA-{now:%Y-%m-%d} projectA
let an external command decide what gets archived. iconic behaviour, no notes
# Use external command to determine files to archive
# Use --paths-from-stdin with find to only backup files less than 1MB in size
$ find ~ -size -1000k | borg create --paths-from-stdin /path/to/repo::small-files-only
# Use --paths-from-command with find to only backup files from a given user
$ borg create --paths-from-command /path/to/repo::joes-files -- find /srv/samba/shared -user joe
# Use --paths-from-stdin with --paths-delimiter (for example, for filenames with newlines in them)
$ find ~ -size -1000k -print0 | borg create \
--paths-from-stdin \
--paths-delimiter "\0" \
/path/to/repo::smallfiles-handle-newline
π bestie pls notice the last one β that's your --paths-delimiter escape hatch for filenames that have newlines in them. cursed filenames handled, we love to see it.
π NOTES π
first up, a pattern PSA because this one trips literally everyone:
the --exclude patterns are not like tar. in tar, --exclude .bundler/gems will exclude foo/.bundler/gems. in borg it will not β you need --exclude '*/.bundler/gems' to get that same effect. no cap. π
besides --exclude patterns, you can also use --exclude-if-present to name a filesystem object (like a file or folder name) that, when it shows up inside another folder, stops that containing folder from being backed up. by default, the containing folder and everything in it gets omitted from the backup. BUT β if you only want to include the objects named by --exclude-if-present and nothing else from that containing folder, you can turn that on with the --keep-exclude-tags option. π
now the -x / --one-file-system thing, and honestly it deserves its own moment because it's sneakier than it looks:
-x or --one-file-system excludes directories that are mount points (and everything inside them). it detects mount points by comparing the device number from the output of stat() of the directory and its parent directory. specifically, it excludes directories for which stat() reports a device number different from the device number of their parent.
in general: be aware that there are directories with device numbers different from their parent, which the kernel does not consider mount points, and vice versa.
- linux examples: bind mounts (possibly same device number, but always a mount point), and all subvolumes of a Btrfs file system (different device numbers from the parent but not necessarily mount points).
- macOS examples: the APFS mounts of a typical macOS installation.
so when you use --one-file-system, double-check that the backup works as intended. fr fr, don't just trust it and dip. π«Ά
Error handling π
when borg runs into a file or directory it can't read (say, permission denied, or another process holding an exclusive lock on Windows), here's the whole move:
- it logs a warning message.
- it skips that file or directory and keeps on backing up the rest of the files.
- it exits with a Warning RC at the end of the operation.
this is so that one single problematic file doesn't abort your entire backup. very demure, very mindful of borg honestly. but the flip side: you should check your logs for these warnings to make sure all your important data is actually being backed up. don't sleep on the warnings, bestie. π
Item flags π¦
--list spits out a list of all files, directories and other file system items it thought about β no matter whether they had content changes or not. for each item it prefixes a single-letter flag showing the type and/or status of that item.
if you only care about a subset of that output, you can do e.g. --filter=AME and it'll only show regular files with A, M or E status (they're all below, keep scrolling).
uppercase letters = the status of a regular file relative to the "files" cache (not relative to the repo β and yes that's an issue if the files cache isn't being used). metadata gets stored in any case, and for 'A' and 'M' new data chunks get stored too. for 'U', all data chunks refer to already existing chunks.
'A'= regular file, added (see alsoa_status_oddityin the FAQ)'M'= regular file, modified'U'= regular file, unchanged'C'= regular file, it changed while we backed it up'E'= regular file, an error happened while accessing/reading this file
lowercase letters = a file type other than a regular file; borg usually just stores their metadata:
'd'= directory'b'= block device'c'= char device'h'= regular file, hardlink (to already seen inodes)'s'= symlink'f'= fifo
other flags used include:
'i'= backup data was read from standard input (stdin)'-'= dry run, item was not backed up'x'= excluded, item was not backed up'?'= missing status code (if you see this, please file a bug report!)
Reading backup data from stdin π
there are two methods to read from stdin. method one: specify - as path and pipe directly into borg:
backup-vm --id myvm --stdout | borg create REPO::ARCHIVE -
method two: use --content-from-command and let borg handle the execution of the command and the piping. if you do that, the first PATH argument is interpreted as the command to execute, and any further arguments are treated as arguments to that command:
borg create --content-from-command REPO::ARCHIVE -- backup-vm --id myvm --stdout
-- is doing the work here β it makes sure --id and --stdout are not considered arguments to borg but rather to backup-vm. periodt.
the difference between the two approaches:
- piping into borg creates an archive even if the command piping into borg exits with a failure. in that case, you can end up with truncated output being backed up. yikes.
- with
--content-from-command, by contrast, borg is guaranteed to fail without creating an archive should the command fail. the command is considered failed when it returned a non-zero exit code.
reading from stdin yields just a stream of data without any file metadata attached to it, and the files cache isn't needed at all. so it's safe to disable it via --files-cache disabled and speed up backup creation a bit. free performance, we love it. β¨
by default, the content read from stdin is stored in a file called 'stdin'. use --stdin-name to change that name.
Feeding all file paths from externally π
usually you hand borg a starting path (a recursion root) and then borg automatically recurses, finds and backs up all fs objects inside it (optionally considering include/exclude rules, obviously).
but if you need more control β like, you want to hand borg every single fs object path yourself, maybe implementing your own recursion or your own rules β you can use --paths-from-stdin or --paths-from-command (with the latter, borg will fail to create an archive should the command fail).
borg supports paths with the slashdot hack to strip path prefixes here too. so be careful not to unintentionally trigger that. π
π SEE ALSO π
borg-common(1), borg-delete(1), borg-prune(1), borg-check(1), borg-patterns(1), borg-placeholders(1), borg-compression(1)
π Author π
The Borg Collective
and that's the whole page, bestie!! this one was borg-create(1) from 2026-07-18, brought to you by the Borg Collective. go forth and archive responsibly πβ¨
π¦ where this page comes from
- alpine 3.24: borgbackup-doc 1.4.5-r0 Β· BSD-3-Clause
- arch rolling: borg 1.4.5-1 Β· BSD
- ubuntu stonking: borgbackup 1.4.5-1 Β· BSD-3-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms