CLI tool · Python · open source
mftp
A command-line FTP client that says what it is doing. Recursive uploads and deletes, a sync that distinguishes uploading from replacing from skipping, and a password that never has to appear in your shell history.
No screenshots on this page — it is a terminal program, so every block below is
the real output, reproduced from the strings in ftp_client.py.
Install
$ pip install mftp_client-1.0.0-py3-none-any.whl Successfully installed mftp-client-1.0.0 colorama-0.4.6 # then, from anywhere $ mftp -H ftp.example.com -u myuser
-p makes the client prompt instead, which keeps the password out of your
shell history — and out of the process list. The help text says so, and puts the
recommended form first.
Connecting
$ mftp -H ftp.example.com -u deploy ============================================================ FTP Client - Type 'help' for available commands ============================================================ Password for deploy@ftp.example.com: Connecting to ftp.example.com:21 with username deploy... ✓ Connected successfully! 220 ProFTPD Server ready. ftp> pwd /home/deploy
Sync, and the three things it can do
sync replaces what is already there; sync-skip leaves it
alone. Each path reports which of the three branches it took, so a deploy log tells you
what actually changed.
sync — replace what is already there
ftp> sync ./dist Directory exists: dist ↻ Replacing: ./dist/index.html -> dist/index.html ✓ Synced: ./dist/index.html -> dist/index.html Created remote directory: dist/assets ↑ Uploading: ./dist/assets/app.css -> dist/assets/app.css ✓ Synced: ./dist/assets/app.css -> dist/assets/app.css ↑ Uploading: ./dist/assets/app.js -> dist/assets/app.js ✓ Synced: ./dist/assets/app.js -> dist/assets/app.js ✓ Synced folder: ./dist -> dist
sync-skip — leave what is already there
ftp> sync-skip ./dist Directory exists: dist ⊘ Skipped (exists): ./dist/index.html -> dist/index.html ⊘ Skipped (exists): ./dist/assets/app.css -> dist/assets/app.css ↑ Uploading: ./dist/assets/vendor.js -> dist/assets/vendor.js ✓ Synced: ./dist/assets/vendor.js -> dist/assets/vendor.js ✓ Synced folder: ./dist -> dist
Removing things, including directories
rm takes as many paths as you give it, notices when one is a directory,
and recurses rather than failing.
ftp> rm old.log cache.tmp legacy/ Removing 3 item(s)... ✓ Removed file: old.log ✓ Removed file: cache.tmp 'legacy/' is a directory, removing recursively... ✓ Removed file: legacy/2023/notes.txt ✓ Removed directory: legacy/2023 ✓ Removed directory: legacy/ ✓ Removed 3/3 item(s)
When it goes wrong
Failures are counted, not swallowed. A batch reports how many of its items actually succeeded.
ftp> upload report.pdf ✗ Not connected to server ftp> connect ftp.example.com deploy hunter2 Connecting to ftp.example.com:21 with username deploy... ✗ Connection failed: 530 Login authentication failed ftp> upload missing.pdf report.pdf Uploading 2 file(s)... ✗ Local file not found: missing.pdf ✓ Uploaded: report.pdf -> report.pdf ✓ Uploaded 1/2 file(s) ftp> quit ✓ Disconnected successfully
The full command set
ftp> help ============================================================ FTP Client - Available Commands ============================================================ Connection: connect <host> <user> <password> [port] - Connect to FTP server disconnect - Disconnect from server quit, exit - Exit the program Navigation: ls [path] - List directory contents cd <path> - Change directory pwd - Print working directory File Operations: rm <file1> [file2] ... - Remove one or more files/directories rmdir <dir1> [dir2] ... - Remove one or more directories recursively upload <file1> [file2] ... - Upload one or more files uploaddir <dir1> [dir2] ... - Upload one or more folders recursively sync <path1> [path2] ... - Sync files/folders (upload new, replace existing) sync-skip <path1> [path2] ... - Sync files/folders (upload new, skip existing) rename <old_name> <new_name> - Rename file or folder Other: help - Show this help message
Flags
| -H, --host | FTP server hostname or IP address. |
|---|---|
| -u, --user | FTP username. Host and user are both required to connect on startup. |
| -p, --password | Not recommended — will prompt if omitted. Passwords with |, &, ; or $ need single quotes if you insist on passing them. |
| -P, --port | FTP port. Defaults to 21. |
colorama, which is what makes the output above readable on
Windows too.