scp Command: Usage and Options, Copying Folders and Specifying a Port
scp is a copy tool for exchanging files with a server you connect to over SSH. When you send a file with the scp command, you write the source first and the destination after it, just as with cp. When we sent files and folders from an AlmaLinux 9 server to a Debian 12 server and retrieved them, the transfer ran over the SFTP protocol and a 20MB file arrived in under a second.
All output below is exactly what scp from OpenSSH 9.9 printed under the root account on the sending side. Only the server addresses and account names were changed to example values.
1️⃣ scp usage and remote paths
Put [account@server address:] in front of a path on the remote server. A path without a colon is treated as a path on the server where you ran the command, so the side with the colon decides whether you are sending or receiving.
Send report.txt from the current folder to the scp-test folder under the remote server's home.
scp report.txt user@203.0.113.10:~/scp-test/report.txt 100% 14 5.1KB/s 00:00When the transfer finishes, the file name, progress, size, speed and elapsed time appear on one line. This progress display only appears when you run scp in a terminal, so if you redirect the output to a file, nothing ends up in that file.
To fetch a file, write the remote path first and the local path to save to after it.
scp user@203.0.113.10:~/scp-test/report.txt ./downloads/report.txt 100% 14 2.7KB/s 00:00If the destination path ends in a file name rather than a folder, the file is saved under that name. After sending with the command below, report.txt sat in the receiving folder as report-1028.txt.
scp report.txt user@203.0.113.10:~/scp-test/report-1028.txtreport.txt 100% 14 4.6KB/s 00:00🔲 scp command simulator
In the simulator below you can type send, receive and folder copy commands yourself and check the output for each option.
2️⃣ scp command options
Options go right after scp, before the source. -P for the port is uppercase and lowercase -p preserves times and permissions, so mixing up the case runs a different action.
-l sets an upper limit on transfer speed in Kbit/s. Without options, a 20MB file finished transferring in under a second.
scp backup.tar.gz user@203.0.113.10:~/scp-test/backup.tar.gz 100% 20MB 53.6MB/s 00:00-l 8000 works out to about 1,000KB per second. When we sent the same file with -l 8000, the progress display showed 996.5KB/s and the transfer took 20 seconds.
scp -l 8000 backup.tar.gz user@203.0.113.10:~/scp-test/backup-l.tar.gzbackup.tar.gz 100% 20MB 996.5KB/s 00:20-C compresses data on the SSH connection in the same way as gzip. We sent a 19MB log file full of repeated sentences three times each, and between these two servers the runs with -C were slightly slower.
| Command | file | Run time | Progress display speed |
|---|---|---|---|
| scp backup.tar.gz | 20MB | 0.68 s | 53.6MB/s |
| scp -l 8000 backup.tar.gz | 20MB | 20.82 s | 996.5KB/s |
| scp access.log (3 runs) | 19MB | 0.79~0.89 s | — |
| scp -C access.log (3 runs) | 19MB | 0.84~0.97 s | — |
Run time is the time from starting the command through connecting to finishing the transfer. The ssh manual also says compression helps on slow lines and slows transfers down on fast networks.
-v prints the steps from connecting to transferring as debug1 lines, so use it to find the cause when a connection fails or stalls at authentication. The output is long, so we picked out only the authentication and transfer lines with grep.
scp -v report.txt user@203.0.113.10:~/scp-test/ 2>&1 | grep -E 'Authenticated|Sending|Transferred'Authenticated to 203.0.113.10 ([203.0.113.10]:22) using "publickey".
debug1: Sending subsystem: sftp
Transferred: sent 2536, received 3248 bytes, in 0.1 secondsThe [Sending subsystem: sftp] line means scp sent the file over the SFTP protocol. From OpenSSH 9.0, scp uses SFTP by default. Adding -O transfers over the legacy SCP protocol, and [Sending command: scp -v -t] appears in the same place.
scp -O -v report.txt user@203.0.113.10:~/scp-test/ 2>&1 | grep -E 'Authenticated|Sending|Transferred'Authenticated to 203.0.113.10 ([203.0.113.10]:22) using "publickey".
debug1: Sending command: scp -v -t ~/scp-test/
Sending file modes: C0600 14 report.txt
Transferred: sent 2328, received 3036 bytes, in 0.1 seconds📌 Main options: results from this article
| Option | Task | Result in this article | |
|---|---|---|---|
| -P | Specifies the SSH connection port | Port 22 finished sending report.txt, while closed port 2222 ended with [Connection timed out] | |
| -i | Specifies the private key file for public key authentication | Finished sending report.txt with ~/.ssh/id_ed25519 specified | |
| -r | Copies a folder's files and subfolders | css and images folders remain on the receiving side in the original structure; without it, the [not a regular file] error stops the transfer | |
| -p | Preserves the source's modification time, access time and permissions | Modification time preserved; on this article's receiving side, permission 600 was kept only for the file sent with -O -p | |
| -C | Compresses data on the SSH connection | For the 19MB log between this article's two servers, the run with it was slightly slower | |
| -l | Sets an upper limit on transfer speed in Kbit/s | With -l 8000, 20MB ran at 996.5KB/s in 20.82 seconds | |
| -v | Prints the steps from connecting to transferring as debug1 lines | SFTP transfer confirmed by the [Sending subsystem: sftp] line | |
| -3 | Transfers data between two remote servers through the server running the command (the default from OpenSSH 8.7) | Finished sending report.txt with two folders on the same server as source and destination | |
| -O | Transfers over the legacy SCP protocol | [Sending command: scp -v -t] appears in the -v output; paths with spaces need an extra backslash | |
| -o | Passes an option in ssh_config format to ssh | Set the wait to 10 seconds with ConnectTimeout=10 and confirmed [Connection timed out] |
📎 Other options: per the official manual
| Option | Task | |
|---|---|---|
| -q | Turns off the progress display and ssh warnings and diagnostic messages | |
| -J | Connects to a jump host first, then sets up TCP forwarding from there to the final destination (shorthand for the ProxyJump setting; separate multiple hops with commas) | |
| -F | Uses a different file as ssh's per-user configuration file (passed directly to ssh) | |
| -4 | Forces use of IPv4 addresses only | |
| -6 | Forces use of IPv6 addresses only |
3️⃣ Copying folders with scp and preserving times
If you give a folder without options, scp prints an error saying it is not a regular file and does not proceed with the transfer.
scp site-files user@203.0.113.10:~/scp-test/scp: local "site-files" is not a regular file
scp: failed to upload file site-files to ~/scp-test/With -r, scp copies the files and subfolders inside the folder.
scp -r site-files user@203.0.113.10:~/scp-test/logo.png 100% 48KB 4.7MB/s 00:00
style.css 100% 15 5.0KB/s 00:00
index.html 100% 15 5.2KB/s 00:00The output shows only file names. The find output on the receiving side showed the css and images folders under site-files in the original structure.
ssh user@203.0.113.10 'cd ~/scp-test && find site-files'site-files
site-files/images
site-files/images/logo.png
site-files/index.html
site-files/css
site-files/css/style.css-r follows symbolic links inside the folder and copies the files they point to, so for folders where links must stay links, use rsync -a.
-p preserves the source's modification time, access time and permissions. We set the source report.txt to a modification time of October 1, 2026 00:00 (UTC) and permissions of 600 before sending it. The receiving server's time zone is UTC, so ls on the sending side also printed with TZ=UTC.
TZ=UTC ls -l report.txt-rw------- 1 root root 14 Oct 1 00:00 report.txtscp -p report.txt user@203.0.113.10:~/scp-test/report-p.txtreport.txt 100% 14 4.7KB/s 00:00scp -O -p report.txt user@203.0.113.10:~/scp-test/report-Op.txtreport.txt 100% 14 4.2KB/s 00:00ssh user@203.0.113.10 'ls -l ~/scp-test/report.txt ~/scp-test/report-p.txt ~/scp-test/report-Op.txt'-rw------- 1 user user 14 Oct 1 00:00 /home/user/scp-test/report-Op.txt
-rw-rw-r-- 1 user user 14 Oct 1 00:00 /home/user/scp-test/report-p.txt
-rw-rw-r-- 1 user user 14 Oct 28 06:17 /home/user/scp-test/report.txtreport-p.txt sent with -p and report-Op.txt sent with -O -p kept the source time, while report.txt sent without options was saved with the time it was sent. On the receiving server, files sent over SFTP were saved with permissions of 664 even with -p, and only the file sent over the legacy SCP protocol (-O) kept 600.
So for files whose permissions must match the source, check the permissions with ls -l on the receiving side after sending.
4️⃣ Specifying a port and key file with scp
For servers you cannot reach with the default port 22 and default key, specify the port and key yourself before sending. -P specifies the SSH connection port and -i specifies the private key file for public key authentication.
Below is an example that specifies port 22 and a key file directly. On a server with a changed port, write that number instead of 22.
scp -P 22 -i ~/.ssh/id_ed25519 report.txt user@203.0.113.10:~/scp-test/report.txt 100% 14 5.3KB/s 00:00Without -i, scp works through the keys with default names under ~/.ssh (id_rsa, id_ecdsa, id_ed25519 and so on) in turn, just as ssh does.
If you send to the same server often, write an alias in ~/.ssh/config and type only the alias in scp.
Host myserver
HostName 203.0.113.10
User user
Port 22
IdentityFile ~/.ssh/id_ed25519The name on the Host line becomes the alias, and the four lines under it stand in for the server address, account, port and key file. The command with only the alias finished with the same one-line result as when we wrote out the address and key.
scp report.txt myserver:~/scp-test/report.txt 100% 14 4.2KB/s 00:00-P, -i and aliases all use your ssh connection settings as they are, so creating a key and registering it on the server also works the same way as connecting with the SSH command.
5️⃣ Copying between servers with scp
Even when both source and destination are remote servers, one line of scp can do the copy. From OpenSSH 8.7, data is transferred through the server running the command, and this method is -3. The official release notes give not having to keep the destination server's credentials on the source server as the reason for making it the default.
The measurement below used two folders on the same server as source and destination. If the destination is a different server, change only the account and address at the end.
scp -3 user@203.0.113.10:~/scp-test/report.txt user@203.0.113.10:~/scp-test/copy3/report.txt 100% 14 2.5KB/s 00:00It is like head office receiving documents from one branch and forwarding them to another.
The old method, in which the source server sends directly to the destination server, is specified with -R. It requires that the source server can connect to the destination server without a password. From OpenSSH 10.6, using -R prints a deprecation warning, and later versions are planned to ignore this option and copy with the -3 method.
6️⃣ scp vs rsync
scp is enough for sending a few files once, but for repeatedly syncing the same folder or resuming an interrupted transfer, use the rsync command. scp sends every file you specify again on each run, while rsync compares source and destination and transfers only the changed files.
| Item | scp | rsync |
|---|---|---|
| Transfer scope | All specified files on every run | Only files changed from the source |
| Keep partially received files (--partial) | ❌ | ✅ |
| Delete files not in the source (--delete) | ❌ | ✅ |
| Symbolic links | Follows them and copies the files | Keeps links as links with -a |
| Needed on the receiving side | SSH access and an SFTP server | rsync installed on both sides |
7️⃣ scp error messages and fixes
When scp fails, the cause appears right on the first line of output. In the three cases where we deliberately triggered errors with a missing file, write permissions and a wrong port, the cause was on the first line every time and the exit code was non-zero every time.
🔲 No such file or directory
If you try to fetch a file that does not exist on the remote side, [No such file or directory] is printed with the path.
scp user@203.0.113.10:~/scp-test/nofile.txt ./downloads/scp: ~/scp-test/nofile.txt: No such file or directoryThe same error appears when the destination folder does not exist on send. scp does not create missing folders, so run mkdir -p over ssh first to create the folder.
scp report.txt user@203.0.113.10:~/scp-test/nodir/sub/scp: dest open "scp-test/nodir/sub/": No such file or directory
scp: failed to upload file report.txt to ~/scp-test/nodir/sub/🔲 Permission denied
If the receiving folder has no write permission, [dest open] is followed by [Permission denied]. Below is the result of sending to a readonly folder with permissions of 555.
scp report.txt user@203.0.113.10:~/scp-test/readonly/scp: dest open "scp-test/readonly/report.txt": Permission denied
scp: failed to upload file report.txt to ~/scp-test/readonly/If [Permission denied] is preceded by [account@server address:] and the parentheses contain an authentication method such as publickey, the connection was refused at the authentication stage. This wording is the format the ssh program uses when authentication fails, so start by checking the key file specified with -i and the public key registered on the server.
🔲 Connection timed out
If the port number is wrong or a firewall blocks that port so no response comes back, scp waits for the connection and ends with [Connection timed out]. Below is the result of sending to closed port 2222 with the wait set to 10 seconds.
scp -P 2222 -o ConnectTimeout=10 report.txt user@203.0.113.10:~/scp-test/ssh: connect to host 203.0.113.10 port 2222: Connection timed out
scp: Connection closedWhen you get this error, first check that the number given to -P matches the server's SSH port.
🔲 Spaces and the tilde (~) in paths
Today's scp, which transfers over SFTP, only needs a remote path containing spaces to be wrapped once in single quotes.
scp report.txt 'user@203.0.113.10:~/scp-test/my files/'report.txt 100% 14 4.7KB/s 00:00When we added -O to the same command to send over the legacy SCP protocol, it failed with [ambiguous target]. This is because the remote shell interprets the path once more in the legacy SCP protocol.
scp -O report.txt 'user@203.0.113.10:~/scp-test/my files/'scp: ambiguous targetIn that case, put a backslash before the space so the remote shell also reads it as one word.
scp -O report.txt 'user@203.0.113.10:~/scp-test/my\ files/'report.txt 100% 14 4.5KB/s 00:00A path after the colon that starts without a slash or tilde is handled relative to the remote account's home folder.
scp report.txt user@203.0.113.10:scp-test/report-rel.txtreport.txt 100% 14 5.6KB/s 00:00The official manual says to use -O when an old SFTP server cannot expand a path starting with a tilde to the home folder. In that case, writing a path relative to home without the tilde, as above, also saves to the same place.
🔢 FAQ & Recommended Content









ℹ️ Affiliate Disclosure
This site's content contains affiliate links. When a visitor buys a product or service through one of them, the site receives a commission from the seller. The amount the buyer pays(it goes down during event discounts ↓)does not go up. Posted prices, discounts, and stock reflect the time of writing and may differ, so confirm with the seller before buying. Products are chosen and reviewed by our own standards, and commissions do not affect the order or content of reviews.
