Before graphical file managers and cloud storage, the File Transfer Protocol (FTP) was the standard way to move files between computers over a network — and it’s still used today in many legacy systems, embedded devices, and internal networks. This article explains, from first principles, how FTP works and how to use Linux’s classic command-line ftp client to connect to a server, navigate directories, and transfer files.
What Is FTP?
FTP (File Transfer Protocol) is a network protocol designed specifically for transferring files between a client and a server. It was defined in the early 1970s and standardized in RFC 959. FTP uses a client-server model: an FTP server listens for connections, and an FTP client (like the Linux ftp command) connects to it, authenticates, and issues commands to list, upload, or download files.
sequenceDiagram
participant Client
participant Server
Client->>Server: Connect on port 21 (control channel)
Server-->>Client: 220 Service ready
Client->>Server: USER username
Server-->>Client: 331 Password required
Client->>Server: PASS password
Server-->>Client: 230 Login successful
Client->>Server: LIST (request directory listing)
Server-->>Client: Opens data channel, sends listing
Client->>Server: RETR filename.txt (download)
Server-->>Client: Sends file over data channel

FTP’s Two Channels
A key concept to understand is that FTP uses two separate connections:
- Control channel (port 21) — used for sending commands and receiving responses (like “login successful” or “file not found”)
- Data channel (port 20, or a dynamically negotiated port) — used for the actual file transfer
This two-channel design is unusual compared to protocols like HTTP, and it’s the reason FTP can be tricky to use through firewalls and NAT — the data channel’s port isn’t fixed and must be negotiated dynamically.
Installing the FTP Client
On most Linux distributions, the classic ftp command isn’t installed by default anymore (it’s considered legacy), but it’s easy to add:
sudo apt install ftp # Debian/Ubuntu
sudo dnf install ftp # RHEL/FedoraConnecting to an FTP Server
ftp ftp.example.comYou’ll be prompted for a username and password:
Connected to ftp.example.com.
220 Welcome to Example FTP Server.
Name (ftp.example.com:user): myusername
331 Please specify the password.
Password:
230 Login successful.
ftp>For anonymous FTP servers (no personal account required), use anonymous as the username and your email address (by convention) as the password.
Basic FTP Commands
Once connected, you interact with an interactive ftp> prompt:
| Command | Purpose |
|---|---|
ls | List files in the current remote directory |
pwd | Show current remote directory |
cd directory | Change remote directory |
lcd directory | Change local directory (on your machine) |
get filename | Download a single file |
put filename | Upload a single file |
mget *.txt | Download multiple files matching a pattern |
mput *.txt | Upload multiple files matching a pattern |
binary | Switch to binary transfer mode (for non-text files) |
ascii | Switch to ASCII transfer mode (for text files) |
delete filename | Delete a file on the server |
mkdir dirname | Create a directory on the server |
bye or quit | Close the connection and exit |
A Practical Example: Downloading a File
ftp ftp.example.com
Name: myusername
Password: ********
ftp> cd /public/documents
ftp> binary
ftp> get report.pdf
ftp> byeThe binary command is important here — text mode (ascii) can corrupt binary files like PDFs, images, or archives by altering line-ending characters during transfer.
A Practical Example: Uploading Multiple Files
ftp ftp.example.com
Name: myusername
Password: ********
ftp> lcd /home/user/photos
ftp> cd /uploads
ftp> binary
ftp> prompt off
ftp> mput *.jpg
ftp> byeThe prompt off command disables the “are you sure?” confirmation for each file when using mget/mput, which is convenient for batch transfers.
Active vs. Passive Mode
FTP’s data channel can be established in two different ways:
| Mode | How the Data Channel Is Opened | Firewall Friendliness |
|---|---|---|
| Active | Server connects back to a port on the client | Poor — often blocked by client-side firewalls/NAT |
| Passive | Client connects to a port the server opens | Good — works better through NAT and firewalls |
To switch to passive mode in the classic ftp client:
ftp> passiveMost modern FTP usage defaults to passive mode precisely because active mode struggles with today’s NAT-heavy networks.
Automating FTP With a Script
You can script FTP transfers non-interactively using a heredoc:
#!/bin/bash
ftp -inv ftp.example.com <<EOF
user myusername mypassword
binary
cd /uploads
put backup.tar.gz
bye
EOFFlags used:
-idisables interactive prompting for multiple file transfers-ndisables auto-login (so the script controls login explicitly)-vshows verbose output
Security note: storing plaintext passwords in scripts is risky. For anything beyond quick, low-security testing, prefer SFTP (over SSH) or FTPS (FTP with TLS), and use a .netrc file with restricted permissions instead of embedding credentials directly.
Using a .netrc File for Credentials
Create ~/.netrc:
machine ftp.example.com
login myusername
password mypasswordSecure the file so only you can read it:
chmod 600 ~/.netrcNow you can connect without typing credentials each time:
ftp ftp.example.comReal-World Use Case: Automated Nightly File Transfer
Many legacy business systems (e.g., some point-of-sale systems, older EDI integrations) still push daily report files to a partner’s FTP server:
#!/bin/bash
# nightly-ftp-upload.sh
ftp -inv reports.partner.com <<EOF
user $(cat /etc/ftp-creds/username) $(cat /etc/ftp-creds/password)
binary
cd /incoming
put /data/reports/daily-$(date +%F).csv
bye
EOF
Scheduled via cron:
0 23 * * * /usr/local/bin/nightly-ftp-upload.sh >> /var/log/ftp-upload.log 2>&1
Comparison: FTP vs. Its More Secure Alternatives
| Protocol | Encrypted? | Port(s) | Notes |
|---|---|---|---|
| FTP | No (plaintext) | 21 (control), dynamic (data) | Legacy, insecure by default |
| FTPS | Yes (TLS) | 21 or 990 | FTP with TLS encryption added |
| SFTP | Yes (SSH) | 22 | Different protocol entirely, runs over SSH |
Whenever possible on new systems, prefer SFTP (sftp command) over plain FTP, since credentials and data are encrypted end-to-end.
Best Practices
- Avoid plain FTP for anything sensitive. Credentials and file contents travel in plaintext unless you use FTPS or switch to SFTP.
- Always use
binarymode for non-text files to avoid corruption. - Use passive mode on networks with firewalls/NAT (which is nearly all modern networks).
- Never hard-code passwords in shell scripts that might be readable by other users; use a
.netrcfile with600permissions, or better, environment variables sourced from a secrets manager. - Automate with clear logging so failed nightly transfers are caught quickly.
- Consider migrating legacy FTP workflows to SFTP or a modern managed file transfer solution wherever business requirements allow.
Troubleshooting
Problem: ftp: connect: Connection refused
The FTP server isn’t running, or a firewall is blocking port 21. Verify with:
telnet ftp.example.com 21Problem: Login works, but ls hangs or times out
This is almost always an active/passive mode mismatch with a firewall. Try:
ftp> passive
ftp> lsProblem: Uploaded/downloaded binary files are corrupted
You forgot to switch to binary mode before the transfer:
ftp> binaryProblem: 530 Login incorrect
Double-check username/password, and confirm the account isn’t locked or restricted to specific IP ranges by the server’s configuration.
Problem: File transfers are extremely slow
This could be due to active mode struggling through NAT, or the server enforcing per-connection bandwidth limits. Test with passive mode and compare transfer speeds.
Conclusion
While largely superseded by more secure protocols like SFTP for new deployments, the classic command-line ftp client remains an important tool to understand — both because many legacy systems and internal networks still depend on it, and because understanding FTP’s two-channel, active/passive design gives valuable insight into how network protocols and firewalls interact. With the commands and scripting techniques in this article, you should be able to confidently connect to, navigate, and transfer files with any FTP server you encounter.