SFTP — SSH File Transfer Protocol — is the standard way to transfer files
over an SSH connection. Unlike the old FTP protocol (which sends credentials
in plain text and requires a separate data channel), SFTP runs entirely inside
the encrypted SSH session. If you can SSH into a machine, you can SFTP into it
without any extra configuration.
SFTP is not FTP over SSH. Despite the similar name, SFTP is a
completely separate protocol developed as part of SSH2. It has nothing in common
with FTP or FTPS — it just happens to do the same job (file transfer) more
securely.
Connecting
The sftp command takes the same arguments as ssh
and supports all the same options — including aliases from your
~/.ssh/config:
# Standard connection — same syntax as ssh
sftp user@hostname# With a non-standard port
sftp -P 2222user@hostname← note: -P not -p (capital P)# Using a specific key
sftp -i ~/.ssh/id_workuser@hostname# Using a config alias (works exactly like ssh)
sftp server
sftp pi
sftp work
philip@laptop — connecting with sftp
philip@laptop:~$sftp serverConnected to server.sftp>← you are now in the sftp prompt
Navigating — Local and Remote at the Same Time
The SFTP shell manages two locations simultaneously: one on the remote machine
and one on your local machine. Most commands come in pairs — the plain version
acts on the remote side, and the version prefixed with l acts
locally.
sftp — navigating remote and local directories
# Remote side — where you are on the serversftp>pwdRemote working directory: /home/philipsftp>lsDesktop Documents Downloads projects wwwsftp>cd www/htmlsftp>ls -ladrwxr-xr-x 2 philip www-data 4096 Jun 15 10:22 .-rw-r--r-- 1 philip www-data 2048 Jun 15 10:22 index.html# Local side — where you are on YOUR machinesftp>lpwdLocal working directory: /home/philipsftp>lcd ~/projects/websitesftp>llsindex.html style.css app.js images/
Uploading and Downloading
Uploading to the server (put)
sftp — uploading files
# Upload a single file to the current remote directorysftp>put index.htmlUploading index.html to /var/www/html/index.htmlindex.html 100% 48KB 240.0KB/s 00:00# Upload to a specific remote pathsftp>put style.css /var/www/html/css/style.css# Upload an entire directory recursivelysftp>put -r images/Uploading images/ to /var/www/html/imagesimages/logo.png 100% 128KB 512.0KB/s 00:00images/hero.jpg 100% 384KB 768.0KB/s 00:00# Upload multiple files using a glob patternsftp>put *.html
Downloading from the server (get)
sftp — downloading files
# Download a file to current local directorysftp>get backup.tar.gzFetching /home/philip/backup.tar.gz to backup.tar.gzbackup.tar.gz 100% 1.2GB 4.8MB/s 04:12# Download to a specific local pathsftp>get nginx.conf ~/backups/nginx.conf.bak# Download an entire directory recursivelysftp>get -r /var/log/nginx/ ~/logs/nginx/# Download multiple files with globsftp>get /var/log/nginx/access.log.*
Managing Files and Directories
sftp — file and directory operations
# Create a directory on the remote serversftp>mkdir uploadssftp>mkdir -p archives/2026/june# Remove a remote filesftp>rm oldfile.html# Remove a remote directory (must be empty)sftp>rmdir old_uploads# Rename / move a remote filesftp>rename draft.html index.html# Check permissions and ownershipsftp>ls -la# Change permissions on a remote filesftp>chmod 644 index.htmlsftp>chmod 755 scripts/deploy.sh# Create a local directory without leaving sftpsftp>lmkdir ~/downloads/server-backup# Run a local shell command with !sftp>!ls -la ~/downloads/sftp>!tar -tzf backup.tar.gz | head
Full Command Reference
Command
Local equivalent
What it does
Example
pwd remote
lpwd
Print current working directory
pwd
ls remote
lls
List directory contents (accepts flags: -la, -lh)
ls -la /var/www
cd remote
lcd
Change directory
cd /var/www/html
mkdir remote
lmkdir
Create a directory
mkdir uploads
put local→remote
—
Upload file(s). -r for recursive
put -r dist/
get remote→local
—
Download file(s). -r for recursive
get -r /var/log/
rm remote
—
Delete a remote file
rm old.html
rmdir remote
—
Remove an empty remote directory
rmdir tmp
rename remote
—
Rename or move a remote file
rename draft.html index.html
chmod remote
—
Change remote file permissions
chmod 644 file.php
chown remote
—
Change remote file ownership (numeric UID)
chown 1000 file.txt
df remote
—
Show remote disk space usage
df
! local
—
Run a local shell command without leaving sftp
!ls ~/downloads
help
—
Print all available sftp commands
help
bye / quit / exit
—
Close the SFTP session
bye
Batch Mode — Non-Interactive Transfers
For scripted or automated transfers, SFTP can read commands from a file with
-b, avoiding the need for an interactive session. Combine with
-q to suppress progress output:
# Create a batch file — one sftp command per line# ~/deploy.sftp
lcd ~/projects/website/dist
cd /var/www/html
put index.html
put style.css
put -r assets/
bye
philip@laptop — running an sftp batch file
# -b batch_file runs commands non-interactivelyphilip@laptop:~$sftp -b ~/deploy.sftp serverUploading index.html to /var/www/html/index.htmlUploading style.css to /var/www/html/style.cssUploading assets/ to /var/www/html/assets# -q = quiet: suppress progress output, errors still showphilip@laptop:~$sftp -q -b ~/deploy.sftp serverphilip@laptop:~$← silent unless something fails# Embed in a shell script for a deploy pipelinephilip@laptop:~$npm run build && sftp -q -b ~/deploy.sftp server
Batch mode aborts on the first error. If a put
fails (file not found, permission denied), SFTP stops and exits with a non-zero
code. For more resilient deploys where you want to continue after errors,
consider rsync instead — covered in the next two chapters.
One-Shot Transfers Without an Interactive Session
You can use scp for simple one-file transfers where the
interactive SFTP shell would be overkill. But SFTP can do the same thing
non-interactively too:
# Upload a single file inline without entering the sftp shell
sftp server:/var/www/html/index.html<<< ""← download trick (rarely used)# The common one-liner for a single upload: still easiest with scp
scp index.html server:/var/www/html/
scp -r dist/ server:/var/www/html/
scp -P 2222file.txt server:~/← capital P for port, same as sftp
SFTP vs SCP — Which to Use
SFTP — use when
You need to browse the remote filesystem
Uploading multiple files interactively
You need to rename, move, or delete remote files
Batch mode scripted deploys
GUI clients (FileZilla, WinSCP use SFTP)
SCP — use when
Quick one-shot copy of a known file or directory
You already know the exact remote path
Copying between two remote machines scp server1:file.txt server2:~/
Simple scripts where rsync would be overkill
For anything beyond a one-off copy, use rsync instead of either.
rsync only transfers what changed, can resume interrupted transfers, and is
far more efficient for directories. SFTP and SCP transfer everything every time.
Chapters 7 and 8 cover rsync in detail.
GUI Clients
If you prefer a drag-and-drop interface to the command line, several excellent
SFTP GUI clients are available. All of them connect using the same credentials
and key files as the sftp command.
FileZilla
Windows · macOS · Linux — Free
The most widely used SFTP client. Two-panel layout (local left, remote right) with drag-and-drop. Import your private key via Edit → Settings → Connection → SFTP → Add key file. Set Protocol to "SFTP – SSH File Transfer Protocol" in the Site Manager.
Tip: Use Site Manager (File menu) to save named connections — it remembers port, user, and key path.
WinSCP
Windows only — Free & open source
Windows-native SFTP/SCP client with deep Windows Explorer integration. Can save sessions, run scripts, and sync folders. Supports PuTTY .ppk key files natively — convert OpenSSH keys with PuTTYgen if needed.
Tip: WinSCP can open a PuTTY terminal in the same session via the Open Terminal button.
Cyberduck
Windows · macOS — Free (donation)
Clean, minimal SFTP client that also supports S3, Google Drive, Backblaze, and more. Good choice if you work with multiple storage providers alongside SFTP. Integrates with the macOS keychain for key passphrase storage.
Tip: Right-click any bookmark → Edit → SSH Private Key to point it at your existing key file.
VS Code — Remote SSH
Windows · macOS · Linux — Free
Not a classic SFTP client, but the Remote-SSH extension lets you open a remote directory in VS Code and edit files directly on the server. Saves the upload/download step entirely for editing workflows. Uses your ~/.ssh/config aliases automatically.
Tip: Install "Remote - SSH" from the Extensions panel. Press F1 → "Remote-SSH: Connect to Host" and pick your config alias.
Practical Workflow — Deploying a Website
philip@laptop — full deploy workflow with sftp
# 1. Build the project locallyphilip@laptop:~$cd ~/projects/website && npm run build✓ Build complete → dist/# 2. Connect to the server with sftpphilip@laptop:~$sftp serverConnected to server.# 3. Navigate remote and local directoriessftp>cd /var/www/htmlsftp>lcd ~/projects/website/dist# 4. Upload changed filessftp>put index.htmlindex.html 100% 12KB 240.0KB/s 00:00sftp>put -r assets/assets/style.css 100% 24KB 480.0KB/s 00:00assets/app.js 100% 88KB 880.0KB/s 00:00# 5. Verify permissions and exitsftp>ls -lasftp>byephilip@laptop:~$
Tab completion works in sftp — press Tab to autocomplete remote
paths and filenames just like in your regular shell. A lifesaver when navigating
deeply nested directories.
Quick Reference
Task
Command
Connect using a config alias
sftp server
Connect to a non-standard port
sftp -P 2222 user@host
Upload a file
put file.html
Upload a directory recursively
put -r dist/
Download a file
get backup.tar.gz
Download a directory recursively
get -r /var/log/nginx/
Change remote directory
cd /var/www/html
Change local directory
lcd ~/projects/dist
Create remote directory
mkdir uploads
Delete remote file
rm old.html
Rename remote file
rename draft.html index.html
Run local command from sftp
!ls ~/downloads
Batch/scripted transfer
sftp -b commands.sftp server
Quick single-file copy (scp)
scp file.txt server:~/
Exit
bye
Next — Chapter 7: rsync Basics.
SFTP transfers whole files every time. rsync is smarter — it compares source
and destination and only sends what changed. Chapter 7 covers how rsync works,
local directory syncing, and the essential flags you'll use in every rsync
command: -a, -v, -z,
--delete, and --dry-run.