If you've used FTP, the SFTP client commands will feel almost identical: ls, cd, get, put, rm, mkdir. What's happening underneath, though, is completely different. Understanding the difference matters because it explains why SFTP is secure by default, why it doesn't have the firewall headaches FTP has, and why you can use SSH keys, MFA, and a single port for everything.
SFTP is not "FTP over SSH"
The name is misleading. SFTP — the SSH File Transfer Protocol, defined in draft-ietf-secsh-filexfer-02 — is not FTP wrapped in encryption. It's a separate protocol that runs as a subsystem of SSH. Different commands, different wire format, different security model.
Side-by-side comparison:
| FTP | SFTP | |
|---|---|---|
| Specification | RFC 959 (1985) | draft-ietf-secsh-filexfer-02 (2001, never finalised) |
| Default port | 21 (control) + ephemeral data port | 22 (single port, shared with SSH) |
| Encryption | None by default. FTPS adds TLS but only after a successful upgrade negotiation. | Always encrypted from the first byte — you can't connect without it. |
| Authentication | Username + password, sent in cleartext over the control channel. | SSH authentication: password, public key, host-based, or any combination including MFA. |
| Connection model | Two connections: control on port 21, data on a separate port per transfer. | One connection. Everything is multiplexed on the single SSH channel. |
| Wire format | Text-based commands (USER, RETR, PASV) and response codes. |
Binary packets with length prefix, type byte, request ID, and payload. |
| NAT / firewall behaviour | Notorious. Requires passive mode and often extra firewall rules to let the data ports through. | Behaves like any other TCP service on one port. No special firewall configuration. |
The single-port property is the practical one. With FTP, the data connection uses a fresh port per transfer, which means firewalls need to do FTP protocol inspection to know which ports to let through. With SFTP, all bytes — control, file content, status — flow on the same encrypted SSH connection on port 22. Nothing else to configure.
How to connect
The simplest way to start an SFTP session is from a terminal:
$ sftp alice@example.com alice@example.com's password: Connected to example.com. sftp>
You can also connect using a public key instead of a password — the recommended approach for any account you'll use more than once:
$ ssh-keygen -t ed25519 # generates ~/.ssh/id_ed25519 and id_ed25519.pub $ ssh-copy-id alice@example.com # adds your public key to the server's authorized_keys $ sftp alice@example.com # no password prompt this time
Once connected, the prompt becomes sftp> and you can type commands interactively.
Moving around
| Command | What it does |
|---|---|
| pwd | Print the current remote directory. |
| cd dir | Change the remote directory. cd .. goes up one level. |
| lpwd | Print the current local directory — where downloads land by default. |
| lcd dir | Change the local directory. |
SFTP keeps a current directory on both ends of the connection. The l-prefixed commands act on the local side.
Listing files
| Command | What it does |
|---|---|
| ls | List the current remote directory. |
| ls -l | Long format with permissions, owner, size, and timestamp. |
| ls pattern | Glob: ls *.csv lists only CSV files. |
| lls | List the local directory (a quick check before put). |
Transferring files
The most common SFTP commands. Everything is one-shot — no separate "open data connection" step.
| Command | What it does |
|---|---|
| get file | Download a file from the remote directory to the local directory. |
| get file dest | Download and save under a different local name. |
| mget pattern | Multi-get — download every matching file. mget *.csv |
| put file | Upload a local file to the remote directory. |
| mput pattern | Multi-put — upload every matching local file. |
| reget file | Resume an interrupted download from where it left off. |
| reput file | Resume an interrupted upload from where it left off. |
Behind the scenes each get turns into a sequence of SFTP packets: SSH_FXP_OPEN to open the file, repeated SSH_FXP_READ requests to pull bytes, and a final SSH_FXP_CLOSE. You won't see these in the prompt, but they're worth knowing if you ever read the protocol spec or have to debug an interop issue.
Creating, deleting, renaming
| Command | What it does |
|---|---|
| mkdir name | Create a directory on the server. |
| rmdir name | Remove an empty directory. |
| rm file | Delete a file. |
| rename old new | Rename or move a file. |
| symlink target link | Create a symbolic link, where the server supports it. |
Permissions and ownership
FTP doesn't have a standard way to change file permissions — you have to use SITE CHMOD, which is vendor-specific. SFTP, because it's modelled on POSIX file attributes, has these built in:
| Command | What it does |
|---|---|
| chmod mode file | Change file mode. chmod 644 report.csv |
| chown uid file | Change owner (server-permitting). |
| chgrp gid file | Change group. |
Help and exit
| Command | What it does |
|---|---|
| ? / help | List supported commands. Type help command for one-line help. |
| !command | Run command in a local shell (e.g. !ls lists the local directory). |
| ! | Open a local shell. Type exit to come back. |
| bye / exit / quit | Disconnect and close the session. |
What to do next
If you're coming from FTP, the muscle memory transfers directly: get, put, ls, cd all do what you expect. The wins are everything you don't have to think about — one port, encrypted, key-based auth, no separate data connection — and they're all happening because SFTP rides on SSH instead of being a layer over FTP.
A few practical next steps:
- Generate an SSH key with
ssh-keygen -t ed25519if you haven't already. It's the modern default and replaces password auth for everything you'll ever automate. - Read
~/.ssh/configdocumentation. It lets you give each host a short alias and store its hostname, port, username, and key path so you can just typesftp prodinstead ofsftp -P 2222 -i ~/.ssh/prod_key alice@prod.example.com. - If you're running a server, configure it to require public-key authentication on automation accounts and to require MFA on human accounts. The same SFTP listener can do both, per account.
- For the gory details of the protocol — packet types, status codes, attribute bitmasks — read the draft specification. It's surprisingly readable.