Quick answer: upload a file to your server, or pull one back:
scp ./backup.tar.gz user@your-server-ip:/home/user/
scp user@your-server-ip:/var/log/app.log ./
The same jobs with rsync, which is faster on repeat runs and can resume:
rsync -avz --progress ./site/ user@your-server-ip:/var/www/site/
rsync -avz user@your-server-ip:/var/backups/ ./backups/
Both ride on SSH: if you can ssh to the machine, you can already copy files to it. Here is how each works and when to reach for which.
scp: the simple copy
scp behaves like cp with a remote side. The remote side is written user@host:path; whichever argument carries the colon is the remote end.
scp local.txt user@host:/tmp/
scp user@host:/etc/nginx/nginx.conf ./
scp -r ./photos user@host:/home/user/photos
-rcopies directories recursively.-P 2222sets a non-default SSH port (capital P, unlike ssh's lowercase).-i ~/.ssh/other_keypicks a specific key, same as ssh.- Paths with spaces need quoting twice for the remote side:
scp "user@host:'/path/with spaces/file'" ./
scp's limits: an interrupted transfer starts over from zero, there is no way to skip files that have not changed, and copying many small files is slow because each is sent whole. For a one-off file or a quick config grab, none of that matters.
rsync: the synchronizer
rsync compares source and destination and transfers only the differences, which makes second and later runs of the same job dramatically faster. The everyday flag set:
rsync -avz --progress ./site/ user@host:/var/www/site/
-aarchive mode: recursive, keeps permissions, ownership where possible, timestamps and symlinks. Almost always what you want.-vverbose,--progressshows per-file progress.-zcompresses in transit; helps on text, wasted effort on already-compressed archives and images.
The trailing slash rule
One rsync quirk trips everyone once: a trailing slash on the source means "the contents of this directory", no slash means "this directory itself".
rsync -av ./site/ user@host:/var/www/site/ # contents into site/
rsync -av ./site user@host:/var/www/site/ # creates site/site/
Resuming interrupted transfers
rsync -avz --partial --progress ./big.iso user@host:/data/
--partial keeps half-transferred files so a dropped connection continues where it stopped instead of restarting. Re-run the same command to resume. (-P in rsync is shorthand for --partial --progress.)
Mirroring with delete
rsync -avz --delete ./site/ user@host:/var/www/site/
--delete removes files on the destination that no longer exist in the source, turning the copy into a true mirror. Handle with care: pointed at the wrong destination it deletes the wrong files. Test first with --dry-run (-n), which prints what would happen without doing it.
Non-default ports and keys
rsync -avz -e "ssh -p 2222 -i ~/.ssh/other_key" ./dir/ user@host:/dir/
rsync has no port flag of its own; you pass the ssh command it should use with -e.
Server to server copies
Both tools can move data between two remote machines. The reliable pattern is to run the command on one of the servers rather than routing through your laptop: SSH into the source box and push straight to the destination:
ssh user@source-host
rsync -avz --progress /var/backups/ user@dest-host:/var/backups/
This needs the source server to have SSH access to the destination (a key pair generated on the source, its public key added on the destination). The transfer then runs at datacenter speed instead of being limited by your home connection.
When the remote files need root
Copying into system paths like /etc or /var/www owned by root fails for a normal user. The clean rsync answer is to elevate only the remote rsync process:
rsync -avz --rsync-path="sudo rsync" ./site/ user@host:/var/www/site/
This works when the remote user has passwordless sudo for rsync. The scp equivalent is clumsier: copy to your home directory first, then sudo mv the files into place over SSH.
Trust, but verify
For transfers that matter, confirm integrity with a checksum on both ends:
sha256sum big.iso
ssh user@host sha256sum /data/big.iso
Matching output means a bit-perfect copy. rsync also has -c, which compares files by checksum instead of size and time; it is slow on large trees but definitive when you suspect a mismatch.
Which one, when
- One file, right now: scp. Nothing to remember beyond cp syntax.
- Deploying a directory repeatedly: rsync. Unchanged files are skipped, so a deploy that once took minutes takes seconds.
- Huge file over a flaky connection: rsync with
--partial. - Keeping a backup folder current: rsync with
--delete, always rehearsed with--dry-run. - Windows local machine: scp ships with Windows 10 and later OpenSSH; rsync needs WSL or a third-party build.
Both tools inherit your SSH setup, so key-based logins, custom ports and ~/.ssh/config aliases all work unchanged. If you have not set up keys yet, do that first and every copy becomes password-free.