Copy, sync and archive: cp, rsync and tar done right

Copy and sync folders without surprises, pack archives with tar, and know what a real backup needs.

Part 12 of 12 in Linux basics for self-hosters. Last updated

In short: rsync -a src/ dest/ copies the contents of src into dest and keeps permissions and timestamps; without the trailing slash on src you get dest/src instead. Add --delete to make dest an exact mirror, but run it with -n (dry run) first. tar -caf backup.tar.zst folder packs a folder into a compressed archive and tar -xf backup.tar.zst unpacks it. A mirror copies your mistakes too, so real backups need versions: restic or borg.

cp: quick local copies

cp notes.txt notes.bak                # one file
cp -a ~/photos /mnt/usb/              # a directory, keeping permissions, owners and times
cp -i big.iso /mnt/usb/               # ask before overwriting
cp --update=none big.iso /mnt/usb/    # never overwrite an existing file

cp -r copies recursively but resets owners and timestamps; cp -a keeps them and is almost always what you want. cp is fine for one-off copies on the same machine. For anything large, repeated or over the network, use rsync: it can resume, and it only transfers what changed.

rsync and the trailing slash

One character decides where your files land: a slash at the end of the source means "the contents of this directory".

rsync -a photos/ /mnt/backup/photos/   # result: /mnt/backup/photos/IMG_0001.jpg
rsync -a photos  /mnt/backup/photos/   # result: /mnt/backup/photos/photos/IMG_0001.jpg
No slash copies the folder; a slash copies what is inside it.

Both forms side by side, run in an empty scratch directory:

$ rsync -a photos backup-a; rsync -a photos/ backup-b; find backup-a backup-b | sort
backup-a
backup-a/photos
backup-a/photos/2026
backup-a/photos/2026/beach.jpg
backup-a/photos/2026/tent.jpg
backup-a/photos/index.txt
backup-b
backup-b/2026
backup-b/2026/beach.jpg
backup-b/2026/tent.jpg
backup-b/index.txt

Real output on openSUSE Tumbleweed, 2026-09-28; user and host names and addresses redacted.

The flags you will use again and again:

rsync -avh --info=progress2 src/ dest/            # verbose file list, overall progress
rsync -avn --delete src/ dest/                    # DRY RUN: what would be copied and deleted
rsync -a --delete src/ dest/                      # make dest an exact mirror of src
rsync -a --exclude '*.tmp' --exclude 'cache/' src/ dest/
sudo rsync -aHAX --numeric-ids /srv/data/ /mnt/backup/data/   # system data: links, ACLs, xattrs, raw IDs

-n (--dry-run) lists every change without making it. Lines starting with deleting are files that will disappear from the destination. Always read that list before the first real --delete run. The man page is long but worth a search: rsync(1).

A dry run against the mirror from above: first nothing to do, then after adding one file and removing another from the source:

$ rsync -av --delete --dry-run photos/ backup-b/
sending incremental file list

sent 143 bytes  received 13 bytes  312.00 bytes/sec
total size is 9  speedup is 0.06 (DRY RUN)
$ touch photos/2026/new.jpg; rm photos/index.txt
$ rsync -av --delete --dry-run photos/ backup-b/
sending incremental file list
deleting index.txt
2026/new.jpg

sent 142 bytes  received 29 bytes  342.00 bytes/sec
total size is 4  speedup is 0.02 (DRY RUN)

Real output on openSUSE Tumbleweed, 2026-09-28; user and host names and addresses redacted.

rsync over SSH

rsync talks SSH by default when either side has a host: prefix. It needs rsync installed on both ends.

rsync -avz ~/photos/ alice@192.168.1.60:/srv/backup/photos/     # push
rsync -avz alice@192.168.1.60:/srv/backup/photos/ ~/restore/     # pull
rsync -avz -e 'ssh -p 2222 -i ~/.ssh/id_ed25519' ~/photos/ alice@192.168.1.60:/srv/backup/photos/
rsync -avz ~/photos/ nas:/srv/backup/photos/                     # with a "Host nas" entry in ~/.ssh/config

-z compresses on the wire, which helps over slow links and costs CPU on a fast LAN; skip it for photos and video, which are compressed already. For unattended jobs, use an ed25519 key and a ~/.ssh/config entry so the command stays short. The SSH key and config helper walks you through both.

tar: archives with gzip or zstd

tar -czf etc.tar.gz /etc                     # create, gzip
tar -caf etc.tar.zst /etc                    # create, compression from the extension (zstd)
tar --zstd -cf etc.tar.zst /etc              # the same, zstd named explicitly
tar -tf etc.tar.zst                          # list the contents
tar -tvf etc.tar.zst                         # list with permissions, owners and dates
tar -xf etc.tar.zst                          # extract here
tar -xf etc.tar.zst -C /tmp/restore          # extract into another directory
tar -xf etc.tar.zst etc/fstab                # extract one file
tar -czf app.tar.gz --exclude='*.log' app/   # leave files out

Read the letters as words: create, extract, list, f for the archive file (always last, directly before its name), z for gzip, a for "pick compression from the name". zstd is faster than gzip at a similar or better ratio. tar strips the leading /, so an archive of /etc extracts as etc/ in the current directory and never over your real /etc. Run it with sudo to read every file and keep owners. Reference: the GNU tar manual.

Create, list and restore the same folder with zstd:

$ tar --zstd -cf photos.tar.zst photos; tar --zstd -tvf photos.tar.zst
drwxr-xr-x user/user         0 2026-09-28 06:36 photos/
drwxr-xr-x user/user         0 2026-09-28 06:36 photos/2026/
-rw-r--r-- user/user         2 2026-09-28 06:36 photos/2026/beach.jpg
-rw-r--r-- user/user         2 2026-09-28 06:36 photos/2026/tent.jpg
-rw-r--r-- user/user         0 2026-09-28 06:36 photos/2026/new.jpg
$ mkdir restore && tar --zstd -xf photos.tar.zst -C restore && find restore -type f | sort
restore/photos/2026/beach.jpg
restore/photos/2026/new.jpg
restore/photos/2026/tent.jpg

Real output on openSUSE Tumbleweed, 2026-09-28; user and host names and addresses redacted.

Why a copy is not a backup

A mirror is only as good as the last run. Delete a folder by accident, or let ransomware encrypt it, and the next rsync --delete faithfully mirrors the damage. A backup needs three things a plain copy lacks:

  • Versions: yesterday's, last week's and last month's state, not just the latest.
  • A second place: a disk in the same machine dies in the same fire, flood or power surge.
  • A tested restore: a backup you have never restored from is a hope, not a backup.

restic and borg keep deduplicated, encrypted snapshots, so a hundred versions cost little more than one:

restic -r /mnt/backup/restic init              # once: create the repository
restic -r /mnt/backup/restic backup ~/photos    # every run: a new snapshot
restic -r /mnt/backup/restic snapshots          # list them
restic -r /mnt/backup/restic restore latest --target /tmp/restore

The rsync and tar backup command builder writes the script, the dry run, a nightly systemd timer and the restore command for you. For your own schedule, the cron schedule builder gives the timer line, and the directory layout guide lists what is worth backing up.

Common mistakes

rsync --delete with the source and destination swapped

rsync -a --delete /mnt/backup/photos/ ~/photos/ makes your photo folder match the (older) backup and deletes every newer picture. Source first, destination second, and a -n dry run before any --delete.

Backing up to an unmounted mount point

If the USB disk or NAS share is not mounted, /mnt/backup is an empty folder on your system disk, and rsync fills it until the disk is full. Start scripts with mountpoint -q /mnt/backup || exit 1.

tar -cvf with the f in the wrong place

f takes the next word as the archive name. tar -cfv backup.tar dir writes an archive called v and tries to add a file called backup.tar. Keep f last: tar -cvf backup.tar dir.

Frequently asked questions

What does the trailing slash mean in rsync?

A slash at the end of the source means 'the contents of this directory': rsync -a photos/ /mnt/backup/photos/ puts the files directly in /mnt/backup/photos. Without it, rsync -a photos /mnt/backup/photos/ creates /mnt/backup/photos/photos. The slash on the destination makes no difference.

How do I extract a tar.gz or tar.zst file?

tar -xf file.tar.gz or tar -xf file.tar.zst; GNU tar recognises the compression by itself. Add -C /target/dir to extract somewhere else, and look inside first with tar -tf file.tar.zst.

Is rsync a backup?

rsync makes a copy. If a file is deleted, damaged or encrypted by ransomware, the next rsync run copies that state over the good version, especially with --delete. A backup keeps several versions over time; restic and borg do that efficiently and encrypt the data.

What does rsync -a do?

-a (archive) is short for -rlptgoD: recursive, keep symbolic links, permissions, modification times, group, owner (when run as root) and device files. It is the right default for copying directories. Add -H, -A and -X for hard links, ACLs and extended attributes.