The standard mput
command in FTP only works with regular files, not directories. When you attempt:
ftp> mput folder1 folder2 folder3
You'll encounter errors like "folder1: not a plain file"
because FTP wasn't designed to handle recursive directory transfers natively.
Here are three effective approaches to transfer directory structures:
1. Using tar + FTP Pipeline
This method preserves permissions and handles binary files well:
# On local server:
tar czf - folder1 folder2 folder3 | ftp -n remote.server.com <
2. ncftp Alternative
The ncftp
package includes recursive transfer capabilities:
ncftp> mkdir -p /remote/path
ncftp> cd /remote/path
ncftp> lcd /local/path
ncftp> mput -R folder1 folder2 folder3
3. Shell Script Automation
For complex transfers, create a script:
#!/bin/bash
FTP_SERVER="remote.server.com"
FTP_USER="username"
FTP_PASS="password"
FOLDERS=("folder1" "folder2" "folder3")
for folder in "${FOLDERS[@]}"; do
find "$folder" -type f -exec curl -u $FTP_USER:$FTP_PASS \
--ftp-create-dirs -T {} ftp://$FTP_SERVER/{} \;
done
For large transfers or unreliable connections:
# Resume capability with lftp
lftp -e "mirror -R folder1 /remote/path; quit" -u user,pass remote.server.com
# Parallel transfers (5 concurrent)
lftp -e "set cmd:parallel 5; mirror -R folder1 /remote/path; quit" remote.server.com
Always prefer SFTP/SCP for sensitive data. For FTP:
# Use .netrc for credentials
machine remote.server.com
login username
password secret
# Set permissions
chmod 600 ~/.netrc
The fundamental issue arises from FTP's mput
command being designed for transferring multiple files, not directories. When you attempt:
ftp> mput folder1 folder2 folder3
FTP client interprets these as individual file transfer requests, not directory operations. The error "not a plain file" confirms this limitation.
For pure FTP solutions without compression, consider these approaches:
# Method 1: Using tar with pipe (no local storage)
tar czvf - folder1 folder2 folder3 | ftp -inv remote.server.com <
Or for individual directory transfers:
# Method 2: Recursive directory upload script
for dir in folder1 folder2 folder3; do
find "$dir" -type f -exec curl --ftp-create-dirs -T {} ftp://user:pass@remote.server.com/{} \;
done
For modern systems, consider superior alternatives:
# SCP (Secure Copy)
scp -r folder1 folder2 folder3 user@remote.server.com:/target/path/
# Rsync (Differential transfers)
rsync -avz folder1 folder2 folder3 user@remote.server.com:/target/path/
For environments requiring FTP, here's a complete automation script:
#!/bin/bash
FTP_SERVER="ftp.example.com"
FTP_USER="username"
FTP_PASS="password"
TARGET_DIR="/remote/path"
ftp -n $FTP_SERVER <
For directories containing mixed file types (binary/text):
find . -type f -exec curl --ftp-create-dirs \
-T {} -k "ftp://user:pass@server.com/{}" \
--ssl --ftp-pasv \;
This handles:
- Directory creation (--ftp-create-dirs)
- SSL encryption
- Passive mode (better for firewalls)
- Recursive directory traversal