How to Recursively Transfer Multiple Directories via FTP Using mput in Unix/Linux


1 views

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