Updated: 8 October 2026 · Applies to: OpenSSH 10.2p1 (Ubuntu 26.04) and 9.9p1 (AlmaLinux 10), rsync 3.4.1 and 3.5.0

To copy a folder recursively, use scp -r. scp has no option to exclude files and no option to skip files that already exist: it always sends everything and overwrites what is on the other side. For either job, use rsync over SSH with --exclude or --ignore-existing.

Copy a folder recursively with scp

scp -r /home/me/site user@server:/var/www/

Where the folder ends up depends on whether the target already exists. We ran each case and listed the result on the receiving side:

  • Target folder exists: scp -r site user@server:/backup/www creates /backup/www/site/index.php and so on.
  • Target does not exist: scp -r site user@server:/backup/new-site creates /backup/new-site/index.php, so the folder is copied under the new name.
  • Trailing slash: scp -r site/ behaves exactly like scp -r site. Unlike rsync, the slash does not mean "contents only".
  • Contents only: scp -r site/* user@server:/backup/www/ copies what is inside site, but the shell's * skips hidden files such as .htaccess.

Useful extras: -p keeps modification times and file modes, -P 2222 (capital P) sets the SSH port and -C turns on compression. According to the OpenSSH manual, scp -r follows symbolic links it finds in the tree, and since OpenSSH 9.0 scp uses the SFTP protocol by default (-O switches back to the legacy protocol for old servers). There is more on recursive copies in How to Copy Folders with scp -r.

Skip files that already exist

scp cannot do this. In our test we changed index.php on the server, ran scp -r again, and the server copy was overwritten. Use rsync instead:

  1. Install rsync on both machines if it is missing: sudo apt install rsync (Ubuntu, Debian) or sudo dnf install rsync (AlmaLinux, Rocky Linux, Fedora).
  2. Preview with a dry run (-n) to see what would be sent.
  3. Run the real copy:
rsync -av --ignore-existing /home/me/site/ user@server:/backup/www/

Real output from our test, where index.php already existed on the server:

sending incremental file list
./
error.log
cache/
cache/c.tmp
img/
img/logo.png

sent 362 bytes  received 92 bytes  908.00 bytes/sec
total size is 12  speedup is 0.03

index.php is not in the list, and the edited copy on the server was kept. Three related choices:

  • --ignore-existing: never touch a file that exists on the receiver, even if yours is newer.
  • --update (-u): skip files that are newer on the receiver, but update older ones.
  • Plain rsync -av: skips files that are already identical (same size and modification time). Our second run of the same command sent no files at all, which makes rsync the better tool for resuming a large copy.

For more on this, see how to sync only new or changed files with rsync.

Exclude files and folders

rsync -av --exclude='*.log' --exclude='cache/' /home/me/site/ user@server:/backup/www/
sending incremental file list
created directory /backup/www
./
index.php
new.txt
img/
img/logo.png
  • Patterns are matched relative to the source folder. A trailing / (cache/) matches folders only.
  • For many patterns, put one per line in a file and use --exclude-from=exclude.txt.
  • A trailing / on the rsync source (site/) copies the folder's contents; without it, rsync creates site inside the target.
  • If SSH listens on another port, add -e 'ssh -p 2222'. See rsync with a non-standard SSH port.

If you can only use scp

When rsync is not available on the server, you have two options that both worked in our tests.

Let Bash pick the files with an extended glob. This sends everything in site except the cache folder and .log files:

shopt -s extglob
scp -r site/!(cache|*.log) user@server:/backup/www/

Or pack the folder with tar, which has its own --exclude, and unpack it on the server in one stream:

tar czf - --exclude='*.log' --exclude='site/cache' site | ssh user@server 'tar xzf - -C /backup'

Both send everything again each time, so for regular copies rsync is still the better choice. For more rsync options, see 13 rsync command examples.

Ucartz services for this topic

Was this answer helpful? 1 Users Found This Useful (1 Votes)