# FTP Folder Sync (Upload)

This utility syncs a local directory to a remote FTP server. It recursively walks through the local folder structure, creates corresponding directories on the server if they don't exist, and uploads all files. This is useful for deploying websites to cPanel/Apache servers.

**Modules Used:**
*   [[programming/python/modules/ftplib-module|ftplib]]: To handle FTP connections and file uploads.
*   `os`: To traverse the local directory structure.
*   [[programming/python/modules/argparse-module|argparse]]: To handle command-line arguments.

## The Code

Save this as `ftp_sync.py`.

```python
import ftplib
import os
import argparse
import sys

def sync_to_ftp(host, user, password, local_dir, remote_dir):
    if not os.path.exists(local_dir):
        print(f"Error: Local directory '{local_dir}' not found.")
        return

    try:
        print(f"Connecting to {host}...")
        # Use ftplib.FTP_TLS(host) if your server requires explicit TLS/SSL
        ftp = ftplib.FTP(host) 
        ftp.login(user, password)
        print(f"Logged in as {user}")

        # Walk through local directory
        for root, dirs, files in os.walk(local_dir):
            # Determine relative path from the base local_dir
            rel_path = os.path.relpath(root, local_dir)
            
            # Determine corresponding remote path
            if rel_path == ".":
                current_remote = remote_dir
            else:
                # Ensure forward slashes for FTP paths regardless of OS
                current_remote = os.path.join(remote_dir, rel_path).replace("\\", "/")

            # Try to create remote directory
            try:
                ftp.mkd(current_remote)
                print(f"Created remote directory: {current_remote}")
            except ftplib.error_perm:
                # 550 error usually means "Directory already exists"
                pass 

            # Upload files in this directory
            for file in files:
                local_file_path = os.path.join(root, file)
                remote_file_path = f"{current_remote}/{file}"
                
                print(f"Uploading {file}...")
                with open(local_file_path, 'rb') as f:
                    # STOR is the FTP command to upload a file
                    ftp.storbinary(f'STOR {remote_file_path}', f)
        
        print("\nSync complete.")
        ftp.quit()

    except ftplib.all_errors as e:
        print(f"FTP Error: {e}")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="FTP Folder Sync (Upload)")
    parser.add_argument("host", help="FTP Server Address")
    parser.add_argument("user", help="FTP Username")
    parser.add_argument("password", help="FTP Password")
    parser.add_argument("local", help="Local directory to upload")
    parser.add_argument("remote", help="Remote destination directory (e.g., /public_html/mysite)")
    
    args = parser.parse_args()
    
    sync_to_ftp(args.host, args.user, args.password, args.local, args.remote)
```

## Usage

```bash
# Upload 'my_website' folder to 'public_html' on the server
python ftp_sync.py ftp.example.com myuser mypassword ./my_website /public_html
```

[[programming/python/python]]