# scp — Secure Copy Over SSH

LLMS index: [llms.txt](/en/llms.txt)

---

scp — a utility for copying files over SSH using the SSH protocol. It works from the terminal, requires no extra server setup — just a running sshd and working authentication. In an era of rsync and bat, SCP survives as a simple tool for one-off transfers when you don't want to deal with daemons or configuration files.

## Syntax and Basic Scenarios

General form:

```bash
scp [flags] source destination
```

Source and destination can be local paths or remote addresses in the format `user@host:path`.

```bash
# Local file to a remote machine
scp ./deploy.tar.gz deploy@10.0.2.15:/opt/app/

# Remote file to the local machine
scp deploy@10.0.2.15:/opt/app/deploy.tar.gz ./

# Between two remote hosts (via the local machine)
scp user@host1:/data/backup.sql user@host2:/data/restore/
```

> [!TIP]
> If the remote host uses a non-standard SSH port, specify it with `-P` (uppercase P — that's how scp differs from ssh).

## Recursive Directory Copying

To copy a directory, the `-r` flag is required. Without it, scp refuses to transfer a directory and prints an error.

```bash
scp -r ./project/ dev@10.0.2.15:/home/dev/projects/
```

> [!WARNING]
> When copying recursively, scp transfers the contents of the directory, not the directory itself. Behavior depends on whether the trailing `/` is present in the path — verify the result if the structure matters.

## Useful Flags

| Flag | Description |
|------|-------------|
| `-r` | Recursive directory copying |
| `-P port` | SSH port on the remote host |
| `-p` | Preserves modification time, access, and file permissions |
| `-q` | Quiet mode, no progress bar |
| `-C` | Compression during transfer |
| `-i key.pem` | Specifies a private key |
| `-o StrictHostKeyChecking=no` | Automatically accepts new host keys |
| `-l rate` | Bandwidth limit in Kbit/s |

```bash
scp -r -p -C -i ~/.ssh/deploy_key.pem -P 2222 ./build/ deploy@10.0.2.15:/var/www/
```

## Typical Transfer Patterns

**Deploying artifacts:**

```bash
scp ./release.tar.gz deploy@prod:/tmp/releases/
```

**Fetching a log from a remote server:**

```bash
scp admin@10.0.2.15:/var/log/app/error.log ./logs/
```

**Transferring multiple files at once:**

```bash
scp config.yaml secrets.env deploy@10.0.2.15:/opt/app/
```

**Direct transfer between two servers** (both source and destination are remote):

```bash
scp -3 user@host1:/data/file.csv user@host2:/data/import/
```

The `-3` flag routes traffic through the local machine. Without it, scp attempts a direct connection between the hosts, which usually fails.

## Limitations and Alternatives

scp does not support resuming interrupted transfers — if the connection drops halfway through a multi-gigabyte file, you start over. There is no incremental sync, no checksum verification. Transfers are sequential, with no built-in parallel file transfer.

For everyday tasks, rsync solves these problems:

```bash
rsync -avz -e "ssh -p 2222" ./build/ deploy@10.0.2.15:/var/www/
```

rsync can resume broken transfers, skip already-copied files, and work incrementally. For one-off transfers of a few small files, scp remains convenient — fewer parameters, faster to type.

> [!NOTE]
> On modern distributions, scp may be wrapped by the OpenSSH client. Behavior is the same, but if you notice differences in output or error handling, that's normal — the implementation depends on the OpenSSH version.
