The scp command, which stands for Secure Copy, is a command-line utility that allows users to copy files and directories between two locations across a network. It utilizes the Secure Shell (SSH) protocol to provide encryption for the data being moved and the credentials used for authentication. Whether you are a system administrator managing multiple servers or a developer deploying code, understanding the nuances of the scp command is fundamental to modern Linux workflows.

In recent years, the landscape of secure file transfers has shifted. As of OpenSSH version 9.0, the scp command has undergone a significant architectural change. While the interface remains the same, the underlying protocol has largely transitioned from the legacy SCP protocol to the more modern and secure SFTP protocol. This evolution ensures that even as the technology ages, it remains a robust choice for quick, secure file movements.

Core Syntax of the SCP Command

The power of the scp command lies in its simplicity. The basic structure mimics the standard cp command used for local file operations, but adds the capability to specify remote hosts.

The general syntax is: scp [options] [source] [destination]

A source or destination can be a local path or a remote location. A remote location is typically defined as: user@host:/path/to/resource

For example, if you want to move a file named report.pdf from your current directory to a remote server's /tmp folder, the command would look like this: scp report.pdf username@192.168.1.50:/tmp/

It is important to note the colon (:) separating the host address from the file path. This colon is the indicator to the shell that the preceding string refers to a remote machine. Without it, scp would simply look for a local file with that name.

Critical Command Options for Daily Use

To handle various network environments and file types, scp provides a wide range of options. Understanding these flags is what separates a basic user from a Linux expert.

Recursive Transfers with -r

By default, scp only handles individual files. If you attempt to copy a directory without the recursive flag, the command will return an error stating that the directory is not a regular file. The -r option tells scp to walk through the directory tree, copying every file and sub-folder contained within.

scp -r ./projects/ dev-user@remote-server:/home/dev-user/backup/

In our testing, we have observed that when using -r, scp follows symbolic links by default. This can sometimes lead to unexpected results if your directory structure contains circular links or links to very large external mount points. Always verify your target directory size if you are unsure about the link structure.

Preserving File Attributes with -p

When you copy a file, the destination file usually receives a new timestamp reflecting the moment of the transfer, and the ownership is set to the user performing the operation. In many administrative scenarios, such as migrating web server content, you need to keep the original modification times, access times, and file modes (permissions).

The -p flag (lowercase) is essential here: scp -p script.sh admin@production-server:/usr/local/bin/

Using -p ensures that a script created three months ago still shows its original creation date on the new server, which is vital for auditing and version control.

Specifying a Non-Standard Port with -P

Security-hardened servers often change the default SSH port from 22 to something obscure to avoid automated brute-force attacks. If your remote server is listening on port 2222, the standard scp command will fail because it defaults to port 22.

The -P flag (uppercase) allows you to specify the correct port: scp -P 2222 data.zip user@remote-host:/home/user/

Note the case sensitivity: -p is for preserving attributes, while -P is for the port. This is a common point of confusion for those transitioning from the ssh command, where the port is specified with a lowercase -p.

Enabling Compression with -C

If you are transferring large text-based files, such as log files or SQL dumps, over a slow network (like a public internet connection), enabling compression can significantly reduce the transfer time. The -C flag enables GZIP compression at the SSH level.

scp -C backup.sql user@remote-host:/backups/

However, a word of caution from our performance benchmarks: on high-speed local area networks (1Gbps or faster), the overhead of the CPU compressing and decompressing the data can actually make the transfer slower than sending the raw data. Compression is a tool meant for bandwidth-constrained environments.

Local to Remote and Remote to Local Workflows

The flexibility of scp allows for data movement in any direction.

Uploading Files to a Remote Server

This is the most frequent use case. You have a local configuration file or a build artifact that needs to go to a server.

scp ./config.yaml root@10.0.0.5:/etc/app/

If you omit the path after the colon, the file will be placed in the remote user's home directory: scp ./config.yaml root@10.0.0.5:

Downloading Files from a Remote Server

To pull a file from a remote server to your current local directory, you simply reverse the order of the arguments. Use a dot (.) to represent the current working directory as the destination.

scp user@remote-host:/var/log/nginx/access.log .

This command fetches the Nginx access log and saves it locally with the same name. If you want to rename the file during the transfer, specify the new name in the destination: scp user@remote-host:/var/log/nginx/access.log ./local_access_backup.log

Transferring Between Two Remote Hosts

A lesser-known capability of scp is the ability to transfer files directly between two remote servers without first downloading them to your local machine.

scp user1@host1:/path/to/source.tar user2@host2:/path/to/destination/

By default, the data flows directly between the two remote servers. However, this requires that host1 can authenticate to host2. If they cannot see each other or if you want the traffic to route through your local machine for security reasons, you can use the -3 flag.

The -3 flag forces the data to be transferred through the local host. While this doubles the total bandwidth used (as data comes to you and is then sent out again), it solves authentication hurdles between the two remote endpoints.

Authenticating with SSH Keys

Entering a password every time you run scp is not only tedious but also prevents the command from being used in automated cron jobs or deployment scripts. The standard solution is using SSH public-key authentication.

If you have multiple SSH keys or your key is not stored in the default location (~/.ssh/id_rsa), you must tell scp which identity file to use with the -i flag.

scp -i ~/.ssh/custom_deploy_key package.tar.gz ubuntu@aws-instance:/tmp/

From an operational security perspective, ensure your private key file has the correct permissions. SSH will reject a key file that is "too open." Before using the key with scp, it is a best practice to run: chmod 400 ~/.ssh/custom_deploy_key

This ensures that only your user can read the file, satisfying the security requirements of the SSH protocol.

Advanced Bandwidth Management

In production environments, a massive file transfer can potentially saturate a network link, causing latency for other applications or users. The scp command includes a built-in "throttle" via the -l option.

The -l flag limits the bandwidth in Kbit/s. Note that this is bits, not bytes. To limit a transfer to roughly 1 MB/s, you would calculate 1024 KB/s * 8 bits/byte = 8192 Kbit/s.

scp -l 8192 large_database_dump.img user@backup-server:/storage/

In our experience, this is particularly useful for background backups where completion time is less important than maintaining network stability for live web traffic.

Troubleshooting with Verbose Mode

When an scp command hangs or returns a "Connection refused" error, the generic message is rarely enough to diagnose the root cause. The -v (verbose) flag is your primary tool for debugging.

scp -v file.txt user@host:/path/

Verbose mode provides a step-by-step account of the SSH handshake. You can see:

  1. Which configuration files are being loaded.
  2. Which authentication methods (public key, password, keyboard-interactive) are being attempted.
  3. Whether the remote server accepted the key.
  4. If there is a mismatch in the "known_hosts" file.

If the output stops at Connecting to host..., the issue is likely a network firewall or an incorrect IP address. If it fails after Offering public key..., the issue is with your SSH key authorization on the remote server.

Security Considerations and the SFTP Transition

As mentioned earlier, the original SCP protocol has architectural flaws. It lacks a way to cleanly handle filenames with spaces or special characters without complex quoting, and it doesn't provide a robust way to validate that the remote server hasn't sent extra, unsolicited files.

Modern versions of scp (specifically those provided by OpenSSH 9.0 and later) mitigate these issues by using the SFTP (SSH File Transfer Protocol) as the transport layer. SFTP is a much more structured protocol that handles file metadata and special characters far more reliably.

When using scp on a modern Linux distribution like Ubuntu 22.04 or Fedora 38, you are likely benefiting from this SFTP backend automatically. If you encounter a legacy server that does not support SFTP, you may need to force the use of the original SCP protocol using the -O (uppercase O) flag:

scp -O file.txt legacy-server:/tmp/

This "Original" protocol flag is a fallback mechanism for backward compatibility.

Comparing SCP with Rsync and SFTP

Choosing the right tool for the job is a hallmark of an experienced developer. While scp is excellent, it is not always the best choice.

SCP vs. Rsync

rsync is often considered the superior tool for synchronization. Unlike scp, rsync uses a "delta-transfer" algorithm, meaning it only sends the parts of a file that have changed.

  • Use SCP when: You need to quickly move a single file or a simple directory to a destination where the files do not already exist. It is lightweight and universally available.
  • Use Rsync when: You are updating an existing set of files, transferring huge amounts of data, or need to resume an interrupted transfer. scp cannot resume a partial transfer; if it fails at 99%, you must start over from 0%. rsync --partial or rsync -P is the solution for unstable connections.

SCP vs. SFTP

SFTP is an interactive file transfer protocol, similar to FTP but encrypted via SSH.

  • Use SCP when: You want a "fire and forget" command in the terminal.
  • Use SFTP when: You need to browse the remote file system, delete files, or perform multiple operations within a single session.

Best Practices for File Ownership and Permissions

A common mistake when using scp is forgetting how permissions translate across systems. If you use scp as the root user to move files into a web developer's home directory, those files will be owned by root. The developer might then find themselves unable to edit or delete their own project files.

After a transfer, it is often necessary to run a chown command on the remote server to fix ownership: ssh user@host "sudo chown -R www-data:www-data /var/www/html/new_site"

Alternatively, always try to scp using the user account that is intended to own the files. If you are uploading to a web directory, use the www-data user if SSH login is enabled for that account, or upload to a temporary directory and move it into place with sudo.

Handling Filenames with Spaces

Because scp passes the destination path to the remote shell, filenames with spaces require double-escaping or careful quoting. This is one of the most frustrating aspects of the legacy protocol.

To copy a file named My Document.pdf: scp "My Document.pdf" user@host:"'/home/user/My Documents/My Document.pdf'"

In this example, the local path is quoted for the local shell, and the remote path is wrapped in single quotes inside double quotes to ensure the remote shell doesn't split the filename into two arguments. With the newer SFTP-based scp, these requirements are significantly relaxed, but for maximum compatibility across different Linux versions, strict quoting remains the safest approach.

Summary

The scp command remains a staple of the Linux ecosystem because of its ubiquity and its reliance on the trusted SSH protocol. While it has evolved to use SFTP under the hood for better security and reliability, the user experience remains focused on a simple, effective command structure. By mastering the use of flags like -r for directories, -P for custom ports, and -i for SSH keys, you can handle almost any file transfer task with confidence.

However, remember that scp is a "copy" tool, not a "sync" tool. For large-scale migrations or fragile network connections where resuming a transfer is necessary, rsync remains the industry standard. For quick, one-off secure transfers, scp is, and likely will remain, the first tool most Linux professionals reach for.

Frequently Asked Questions

Why does SCP ask for a password even though I added my SSH key?

This usually happens because the remote server's authorized_keys file has incorrect permissions or the SSH agent isn't running on your local machine. Ensure your remote ~/.ssh directory is set to 700 and ~/.ssh/authorized_keys is set to 600. You can also use ssh-add to ensure your key is loaded into your current session.

Can SCP transfer files between two Windows machines?

Yes, modern versions of Windows 10 and Windows 11 include OpenSSH. You can use the scp command in PowerShell or Command Prompt just as you would in a Linux terminal, provided the OpenSSH Server feature is enabled on the destination machine.

Is SCP faster than FTP?

In most cases, raw FTP is faster than SCP because it does not have the overhead of encryption. However, FTP sends data in plain text, including your password. The security risk of FTP is almost never worth the slight speed advantage. If you need speed and security, use scp with a faster encryption cipher like aes128-gcm via the -c option.

How do I see the progress of an SCP transfer?

By default, scp shows a progress bar in the terminal. If you are not seeing it, ensure you haven't enabled "quiet mode" with the -q flag. If you are redirecting output to a file or a script, the progress meter is automatically disabled to prevent log clutter.

What is the difference between -p and -P in SCP?

In the scp command, -p (lowercase) is used to preserve file attributes like timestamps and permissions from the source file. -P (uppercase) is used to specify the destination port if the remote SSH server is not running on the default port 22.

Can I use wildcards with SCP?

Yes, you can use wildcards like *.jpg. However, if the wildcard is intended for the remote server, you must escape it so your local shell doesn't expand it first. For example: scp user@remote:/path/to/images/\*.jpg ./local_dir/. The backslash ensures the asterisk is passed to the remote server's shell.