| |

LFCS 116 ๐Ÿง Remote Transfer โ€” scp

โฑ๏ธ Estimated read: 11 min | |

The scp command copies files between hosts over an SSH connection. It is one of the oldest tools in the OpenSSH suite, and its implementation has changed significantly in recent years. Since OpenSSH 9.0, scp uses the SFTP protocol by default, not the legacy SCP protocol that shared its name. This means the transfer is more secure, but it also means some of the old wildcard behaviors and path expansions no longer work the way they did in older tutorials. The LFCS exam tests the basic syntax, the recursive flag, and the permission-preservation flag. The critical trap is the remote path specification: host:path is interpreted as remote, but host:path on a local file containing a colon is interpreted as a hostname. The fix is to use ./ or an absolute path for local files with colons.

Key point: The syntax is scp [options] source target. A remote source or target is specified as [user@]host:[path]. The -r flag copies directories recursively. The -p flag preserves modification times, access times, and permissions. The -P flag (capital) specifies the SSH port, not the -p flag (lowercase), which is for preservation.


Why scp exists and how it changed

The secure transfer problem. Before scp, file transfer between Unix systems used rcp (remote copy), ftp (File Transfer Protocol), or telnet. None of these encrypted the data. The password, the file contents, and the commands traveled in plaintext. scp was introduced as part of the SSH suite to provide the same functionality over an encrypted connection. It uses the same authentication as SSH: keys, passwords, and agent forwarding all work the same way .

The protocol migration problem. The original scp used the SCP protocol, a simple protocol that ran a remote scp process over an SSH connection. The protocol had limitations: it could not handle files larger than 2 GB on some systems, it did not support resuming interrupted transfers, and its wildcard expansion was handled by the remote shell, which created quoting problems. OpenSSH 8.8 announced the deprecation of the SCP protocol, and OpenSSH 9.0 made SFTP the default. The change was transparent for most users, but it eliminated the need for double-quoting shell metacharacters in remote paths . The legacy protocol is still available with the -O flag, but it is not recommended.

The remote-to-remote problem. Copying a file from one remote host to another through a local machine requires the data to pass through the local machine’s memory. The scp host1:file host2:file command does this by default. The -3 flag is the default in OpenSSH 9.0 and later. The alternative is -R, which connects to the origin host and executes scp there, transferring the data directly between the two remote hosts. This requires that the origin host can authenticate to the destination host without a password . The direct mode is faster because the data does not traverse the local machine’s network connection twice.

The permission problem. A file copied with scp receives the permissions of the destination user’s umask, not the permissions of the source file. A script that is executable on the source machine (755) becomes non-executable on the destination machine (644) unless the -p flag is used. The -p flag preserves the modification time, access time, and permissions . The -r flag is required for directories; without it, the command fails with “not a regular file.”

The trade-off. scp is simple and universally available on systems with OpenSSH installed. It is not the fastest transfer method for large files or directories with many small files. rsync is faster for incremental transfers because it compares the source and destination and transfers only the differences. sftp provides an interactive session for browsing and transferring files. The exam tests scp because it is the baseline tool, but the practical recommendation for large or repeated transfers is rsync.


a. The basic syntax and remote path specification

The scp command takes a source and a target. Either or both can be remote. A remote path is specified as [user@]host:[path]. A local path is a normal pathname.

# Copy a local file to a remote host
scp report.pdf user@server.example.com:/home/user/

# Copy a remote file to the local machine
scp user@server.example.com:/var/log/syslog ./

# Copy a file between two remote hosts (through the local machine)
scp user@host1:/path/file user@host2:/path/

The remote path after the colon is relative to the remote user’s home directory unless it begins with /. If the path is omitted, the file is placed in the home directory. The user@ prefix is optional; without it, the local username is used .

The colon is the separator between the host and the path. A local file whose name contains a colon is interpreted as a remote host. The fix is to prefix the local path with ./ or use an absolute path.

# A local file named "report:2026.txt" would be misinterpreted
# Correct:
scp ./report:2026.txt user@server:/path/

The -P flag specifies the SSH port. The capital P is the port, and the lowercase p is for preservation. This is a common source of confusion.

# Connect to port 2222
scp -P 2222 file.txt user@server:/path/

b. Recursive copying and permission preservation

The -r flag copies a directory and its contents recursively. Without it, scp fails on directories.

# Copy a directory recursively
scp -r ./project user@server:/home/user/

# Copy a directory recursively and preserve permissions
scp -rp ./project user@server:/home/user/

The -p flag preserves the modification time, access time, and permissions of the source files. Without it, the destination files receive the permissions determined by the remote user’s umask. A file that was executable on the source machine will not be executable on the destination machine unless -p is used .

The -C flag enables compression. It passes the -C flag to ssh, which compresses the data before transmission. This is useful for slow network connections and text files, but it adds CPU overhead on both ends. For already-compressed files (images, videos, archives), the compression has no effect and only adds overhead.

# Compress during transfer
scp -C large-text-file.txt user@server:/path/

The -l flag limits the bandwidth in Kbit/s. This is useful when the transfer would otherwise saturate the network connection.

# Limit to 500 Kbit/s
scp -l 500 large-file.iso user@server:/path/

c. Agent forwarding, jump hosts, and batch mode

The -A flag forwards the local SSH agent to the remote host. This is useful when the remote host needs to authenticate to a third host. The -J flag specifies a jump host, which is the modern replacement for the older ProxyCommand configuration.

# Jump through a bastion host
scp -J bastion.example.com file.txt internal.example.com:/path/

# Forward the agent (use with caution)
scp -A file.txt user@server:/path/

The -B flag enables batch mode. It prevents scp from asking for passwords or passphrases. This is the correct setting for scripts and CI pipelines where an interactive prompt would hang the process. The authentication must be key-based for batch mode to succeed.

# Batch mode for scripts
scp -B -i ~/.ssh/id_ed25519 file.txt user@server:/path/

The -i flag specifies the identity file (private key). It is passed directly to ssh. The -F flag specifies an alternative SSH configuration file. The -o flag passes an arbitrary SSH option.

# Use a specific key and SSH config
scp -i ~/.ssh/work_key -F ~/.ssh/config_work file.txt user@server:/path/

Complete Example Session

# ============================================
# PART 1: COPY A LOCAL FILE TO A REMOTE HOST
# ============================================

scp report.pdf user@server.example.com:/home/user/
# report.pdf is copied to /home/user/report.pdf
# ============================================
# PART 2: COPY A REMOTE FILE TO THE LOCAL MACHINE
# ============================================

scp user@server.example.com:/var/log/syslog ./
# syslog is copied to the current directory.
# ============================================
# PART 3: COPY A DIRECTORY RECURSIVELY
# ============================================

scp -r ./project user@server:/home/user/
# The entire directory tree is copied.
# ============================================
# PART 4: PRESERVE PERMISSIONS AND TIMES
# ============================================

scp -rp ./scripts user@server:/home/user/
# The executable bit on scripts is preserved.
# ============================================
# PART 5: SPECIFY A NON-STANDARD PORT
# ============================================

scp -P 2222 file.txt user@server:/path/
# Connects to port 2222.
# ============================================
# PART 6: COPY BETWEEN TWO REMOTE HOSTS
# ============================================

scp user@host1:/path/file user@host2:/path/
# Data passes through the local machine by default.
# ============================================
# PART 7: DIRECT REMOTE-TO-REMOTE TRANSFER
# ============================================

scp -R user@host1:/path/file user@host2:/path/
# host1 connects directly to host2.
# Requires passwordless authentication between host1 and host2.
# ============================================
# PART 8: BATCH MODE FOR SCRIPTS
# ============================================

scp -B -i ~/.ssh/id_ed25519 file.txt user@server:/path/
# No password prompt. Fails if key auth is not configured.
# ============================================
# PART 9: VERIFY THE TRANSFER
# ============================================

ssh user@server "ls -la /home/user/report.pdf"
# Confirms the file exists and shows its permissions.

The nine parts trace the scp workflow: local-to-remote, remote-to-local, recursive, preservation, port, remote-to-remote, direct mode, batch mode, and verification.


Quick Reference

scp Options

OptionPurpose
-rRecursive copy (directories)
-pPreserve times and permissions
-P <port>SSH port
-CCompression
-l <kbit>Bandwidth limit
-BBatch mode (no prompts)
-i <key>Identity file
-J <host>Jump host
-AForward SSH agent
-3Remote-to-remote through local (default)
-RDirect remote-to-remote

Path Formats

FormatMeaning
file.txtLocal file
./file:name.txtLocal file with colon
user@host:fileRemote file (home directory)
user@host:/path/fileRemote file (absolute path)
user@host:Remote home directory

Common Errors

ErrorCauseFix
Permission deniedNo write access on destinationCheck permissions
Not a regular fileDirectory without -rAdd -r
Host key verification failedUnknown hostAccept key or use -o StrictHostKeyChecking=accept-new
Connection refusedWrong port or SSH not runningCheck -P and sshd status

Best Practices

โœ… Do This:

scp -rp ./project user@server:/home/user/
<!-- Use -r and -p for directories -->               # โœ…
scp -B -i ~/.ssh/key file.txt user@server:/path/
<!-- Use batch mode and explicit key in scripts -->   # โœ…
scp ./report:2026.txt user@server:/path/
<!-- Prefix local colon files with ./ -->             # โœ…

โŒ Don’t Do This:

scp -p 2222 file.txt user@server:/path/
<!-- Lowercase p is preservation, not port -->        # โŒ
# Copy a directory without -r
<!-- Fails with "not a regular file" -->              # โŒ
# Assume wildcards work the same as legacy scp
<!-- SFTP default changes expansion behavior -->      # โŒ

Common Pitfalls

PitfallWhy It HappensFix
Directory copy failsMissing -rAdd -r
Wrong portUsed -p instead of -PCapital P
Local file treated as remoteColon in filenamePrefix with ./
Permissions lostMissing -pAdd -p
Wildcard does not expandSFTP defaultUse rsync or legacy -O

Real-World Examples

1. Copy File to Remote

scp file.txt user@server:/path/

2. Copy File from Remote

scp user@server:/path/file.txt ./

3. Copy Directory

scp -r ./dir user@server:/path/

4. Preserve Permissions

scp -p file.txt user@server:/path/

5. Non-Standard Port

scp -P 2222 file.txt user@server:/path/

6. Batch Mode

scp -B file.txt user@server:/path/

7. Specific Key

scp -i ~/.ssh/key file.txt user@server:/path/

8. Jump Host

scp -J bastion file.txt internal:/path/

9. Remote-to-Remote

scp user@host1:/file user@host2:/path/

10. Compression

scp -C file.txt user@server:/path/

Visual

Local to Remote

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Local machine                               โ”‚
โ”‚  file.txt                                    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ”‚ scp file.txt user@server:/path/
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Remote server                               โ”‚
โ”‚  /path/file.txt                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Remote to Local

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Remote server                               โ”‚
โ”‚  /path/file.txt                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ”‚ scp user@server:/path/file.txt ./
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Local machine                               โ”‚
โ”‚  ./file.txt                                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Remote to Remote (Through Local)

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Remote host1                                โ”‚
โ”‚  /file                                       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ”‚ scp user@host1:/file user@host2:/path/
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Local machine (relay)                       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Remote host2                                โ”‚
โ”‚  /path/file                                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Syntaxscp [options] source target
Remote format[user@]host:[path]
Recursive-r
Preserve-p
Port-P (capital)
Batch mode-B
Key-i
Jump host-J
Protocol defaultSFTP (OpenSSH 9.0+)
Legacy protocol-O

Key takeaways:

  • scp copies files over SSH. The syntax is source target, and either can be local or remote. The remote format is [user@]host:[path] .
  • The -r flag is required for directories. Without it, scp fails with “not a regular file.” The -p flag preserves permissions and timestamps .
  • The capital -P is the port. The lowercase -p is preservation. This is the most common flag confusion.
  • The default protocol is SFTP since OpenSSH 9.0. The legacy SCP protocol is available with -O, but it is deprecated and has different wildcard behavior .
  • Batch mode is mandatory for scripts. The -B flag prevents password prompts that would hang a non-interactive process.
  • Local files with colons must be prefixed. ./report:2026.txt is a local file; host:path is remote.

Remember: scp is the baseline secure transfer tool. It is simple, universally available, and sufficient for single files and small directories. For large transfers or repeated synchronization, rsync is faster and more resilient. For interactive browsing, sftp is the correct tool. The exam tests scp because it is the foundation.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!