scp — Securely copy files between hosts over SSH across all 5 shells
Equivalents in every shell
Bashunix
scp local.txt user@host:/tmp/Zshunix
scp local.txt user@host:/tmp/Fishunix
scp local.txt user@host:/tmp/PowerShellwindows
scp local.txt user@host:/tmp/Bundled with the OpenSSH Client optional feature, same as `ssh.exe`. Use forward slashes for the remote path.
Worked examples
Copy a remote file down to the local current directory
Bash
scp user@host:/etc/nginx/nginx.conf ./Fish
scp user@host:/etc/nginx/nginx.conf ./PowerShell
scp user@host:/etc/nginx/nginx.conf .\Recursively upload a directory
Bash
scp -r ./dist user@host:/var/www/Fish
scp -r ./dist user@host:/var/www/PowerShell
scp -r .\dist user@host:/var/www/Use a non-default SSH port
Bash
scp -P 2222 local.txt user@host:/tmp/PowerShell
scp -P 2222 local.txt user@host:/tmp/Gotchas
- `scp` uses uppercase `-P` for the port. `ssh` uses lowercase `-p`. Mixing them up is the single most common scp error.
- OpenSSH 9.0 (2022) switched `scp` to use the SFTP protocol under the hood and deprecated the legacy SCP wire protocol. Old servers without SFTP will need `-O` (uppercase O, "old protocol") to keep working.
- Paths with spaces need double escaping: `scp 'user@host:/path with spaces/file'` — the local shell strips one layer of quoting, the remote shell strips another.
- `scp` does NOT preserve symlinks by default — it follows them. For a faithful directory copy use `rsync -av` instead.
- On Windows, `scp` uses Windows-style local paths (`C:\foo`) but always Unix-style remote paths (`/tmp/foo`). Mixing them up usually fails silently with a 'No such file or directory' error.
WSL & PowerShell Core notes
pwshPowerShell Core does not bundle scp — it calls the system `scp.exe`. The flag set is identical across platforms because it is just OpenSSH.
WSLWSL `scp` (from openssh-client) and Windows `scp.exe` are entirely separate binaries with separate `known_hosts` and `~/.ssh/config`. Either pick one and stick with it, or symlink your keys + config so both work.