>_cmd.script

scp

Securely copy files to/from a remote host over SSH

Networking

By CMD Script Team · 4 min read · Last updated

SYNTAX
scp [OPTIONS] SOURCE... DESTINATION

Options

Command options and flags
FlagDescription
-rRecursively copy entire directories
-PConnect to a non-default remote port (uppercase, unlike ssh's -p)
-iUse a specific identity (private key) file for authentication
-pPreserve modification times, access times, and modes from the source
-CCompress data during transfer
-vVerbose mode, useful for debugging connection problems
-lLimit bandwidth used, in Kbit/s

Distribution compatibility

  • Ubuntu
  • Debian
  • Fedora
  • Arch
  • macOS

What it does

scp (secure copy) copies files and directories between hosts over an encrypted SSH connection, using the same authentication (passwords, keys, agents) as ssh. It's the go-to one-shot command when you just need to move a file or directory to or from a remote machine without opening an interactive session — unlike sftp, there's no prompt to navigate, you specify source and destination and it copies immediately.

Beginner examples

  • scp file.txt user@host:/home/user/ — copy a local file to a remote directory
  • scp user@host:/etc/hostname ./hostname-backup — copy a remote file to the local machine
  • scp -r ./project user@host:/tmp/project — recursively copy a local directory to a remote host
  • scp file1.txt file2.txt user@host:/tmp/ — copy multiple local files in one command
scp notes.txt user@server.example.com:/home/user/notes.txt

Advanced examples

  • Copy on a non-default SSH port: scp -P 2222 file.txt user@server.example.com:/tmp/
  • Preserve timestamps and permissions during the copy: scp -p config.yml user@host:/etc/app/config.yml
  • Copy directly between two remote hosts (traffic flows host-to-host, not through your machine): scp user1@hostA:/data/report.csv user2@hostB:/backup/
  • Force the copy through your local machine when direct host-to-host isn't possible: scp -3 user1@hostA:/data/report.csv user2@hostB:/backup/
  • Copy a wildcard set of remote files down to the local machine: scp 'user@host:/var/log/*.log' ./logs/
scp -r -P 2200 -i ~/.ssh/deploy_key ./dist deploy@server.example.com:/var/www/app

Common mistakes

  • Forgetting to quote wildcard remote paths (user@host:/var/log/*.log) — without quotes, the local shell tries to expand the glob against the local filesystem before scp ever sees it.
  • Omitting -r when copying a directory and getting a "not a regular file" error.
  • Confusing -p (preserve attributes) with -P (port) — using the wrong case either connects to the wrong port or silently does nothing useful.
  • Assuming scp merges into an existing remote directory the way cp does locally — trailing slashes and existing-directory checks behave slightly differently than local cp, so always double check the destination path.

Tips

  • Use -C to enable compression, which helps a lot when copying large, compressible files (like text logs or source trees) over a slow link.
  • Add -v when a transfer silently fails or hangs — it shows the SSH negotiation steps and usually reveals the real problem (wrong key, wrong port, host key mismatch).
  • For repeated or partial transfers (resuming, only-changed-files), reach for rsync -e ssh instead — scp always re-copies the whole file every time.

Best practices

  • Prefer key-based authentication with ssh-agent over typing passwords, especially in scripts or CI pipelines that call scp non-interactively.
  • Use -r deliberately and check what you're copying — recursive copies can pull in far more than intended if a directory contains build artifacts, .git, or node_modules.
  • For anything beyond an occasional one-off copy, prefer rsync — it avoids re-transferring unchanged data and handles interrupted transfers far more gracefully.

Try it yourself

A simulated shell with a sample home directory — experiment freely, nothing leaves your browser. Type help to list supported commands.

Real-world use cases

  • Pulling a log file off a production server for local debugging: scp prod:/var/log/app/error.log ./.
  • Deploying a built frontend bundle to a web server: scp -r ./dist deploy@web1:/var/www/app.
  • Grabbing a database backup dump from a remote host before restoring it locally.

Common interview questions

  • How does scp differ from sftp? scp is a single, non-interactive copy command (source and destination given up front); sftp opens an interactive session for browsing and transferring files. Both run over SSH.
  • Why does scp use -P for the port while ssh uses -p? Because scp already used lowercase -p to mean "preserve file attributes" (mirroring cp -p), so the port flag had to be uppercase to avoid a collision.
  • How would you copy a file between two remote servers without downloading it locally first? scp user1@hostA:/path/file user2@hostB:/path/, run from a machine that can reach both hosts (data flows directly between them unless -3 is used to route it through the local machine).

Frequently Asked Questions

How do I copy a file to a remote server with scp?

scp localfile.txt user@remote-host:/path/on/remote/ — scp uses the familiar cp-like SOURCE DESTINATION syntax but with host:path for anything remote.

Why does scp use -P for port but ssh uses -p?

Historical inconsistency: scp reserved lowercase -p for 'preserve file attributes' (matching cp -p), so it had to use uppercase -P for the port, unlike ssh which uses lowercase -p for the port.

Is scp deprecated?

OpenSSH has deprecated the legacy scp protocol in favor of using SFTP under the hood for transfers, but the scp command itself is still shipped and widely used; newer OpenSSH versions transparently use SFTP unless you force the old protocol.

How do I copy between two remote hosts?

scp user1@hostA:/path/file user2@hostB:/path/ copies directly between two remote machines when run from a third host that can reach both (add -3 to route the data through the local machine if direct host-to-host connectivity isn't available).

Cheat sheet

Download a quick-reference cheat sheet for scp.