FileZilla Pro CLI: scheduled/scripted transfers

If you’re automating backups, deployments, or routine file sync with FileZilla Pro CLI (fzcli), three questions come up again and again in the FileZilla Pro community: how do I exclude the right files, why doesn’t my scheduled task run the way it does when I test it manually, and what’s the actual syntax for keeping two directories in sync? This guide walks through all three, using the CLI’s documented commands.

Connecting Without Hardcoding Credentials

You can connect with a raw URI:

fzcli> connect ftp://user:password@ftp.server.net

For anything you plan to run unattended, use a saved Site Manager entry instead — it keeps credentials out of your script file:

fzcli> site "0/My Backup Server"

or equivalently:

fzcli> connect --site "0/My Backup Server"

The 0/ prefix means a user-defined Site Manager entry (use 1/ for a default/built-in entry), followed by the full site path.

Important if you use a master password: if the site is protected by FileZilla Pro’s master password feature, connecting will prompt for that password interactively. A script running unattended through Windows Task Scheduler has no one there to type it — so a scheduled job built around a master-password-protected site will hang or fail silently. Either use a site that isn’t behind the master password for automated jobs, or account for this before you schedule anything.

A master pasword can be provided with the secret command:

secret mymasterpassword

Single Files and Whole Directories

Single files:

fzcli> put budget.xlsx
fzcli> get budget.xlsx

Whole directories, recursively:

fzcli> rput Pictures
fzcli> rget Pictures

Add a second argument if you want the transfer to land inside a newly created directory of the same name rather than merging into the current one:

fzcli> rput Pictures Pictures

Keeping Two Directories in Sync

For routine sync jobs — the most common case for a scheduled task — use sync rather than rput/rget. It only transfers what’s actually changed:

sync [options]  

Key options:

  • -d, --direction: localtoremote (upload), remotetolocal (download), or bidirectional (two-way, no deletions)
  • -e, --exists: how to treat files that exist on both sides — ignore (skip), newer (sync if source is newer), size (sync if sizes differ), or sizeornewer
  • -r, --recursive: include subdirectories
  • -p, --preview: show what would happen without actually transferring anything
  • -t, --rootonly: apply filters only at the top level, not inside subdirectories

A one-way upload sync that only pushes newer files:

sync --direction localtoremote --recursive --exists newer /Files/website/public_html /public_html

A one-way download used for backups:

sync --direction remotetolocal --recursive --exists newer /Documents/backup /files/documents

Run any sync command with --preview first the first few times you run it on a schedule — it costs nothing and confirms the job will do what you expect before it’s unattended.


Filtering and Excluding Files

This is the part that trips people up most often, so here’s the full syntax. Filtering works via --exclude, and it’s available on lls, mput, mget, rput, rget, mrn, lmrn, mdel, lmdel, and sync.

Basic format:

--exclude "type condition value"

Name/path conditions:

  • name has text — matches if the filename contains text
  • name hasnot text — matches if it does not
  • name = text — exact match
  • name begins text / name ends text
  • name rx pattern — regular expression

Size conditions: size > number, size < number, size = number, size != number (bytes).

Date conditions: date > YYYYMMDD[HHMMSS], date < YYYYMMDD[HHMMSS], date = YYYYMMDD[HHMMSS].

Permission conditions: perm set rwxrwxrwx, perm !set rwxrwxrwx.

Example — skip anything that looks like a temp file when syncing:

sync --direction localtoremote --recursive --exclude "name ends .tmp" /local/path /remote/path

When you combine multiple --exclude conditions, --match controls how they combine:

  • all (default) — every condition must match
  • any — at least one condition matches
  • notall — not every condition matches
  • none — no condition matches

If your filter "isn't working," check --match first — a common mistake is stacking two --exclude conditions expecting any-style "match either" behavior when all is the default. Also note that name/path matching is not case-sensitive by default; add --case if you need exact case matching, and wrap any value containing spaces in escaped quotes.


Turning Commands Into a Script

Save your commands (connect, filters, sync, etc.) into a plain text script file, then run it in standalone mode:

fzcli --mode standalone --script D:\Scripts\script-file

You can also set a default local working directory for the script with --local-path:

fzcli --mode standalone --local-path D:\Files --script D:\Scripts\script-file

Enabling File logging

Use the engine.log.file setting to specify a file where FileZilla Pro CLI should write its log output. For example:

# Enable debug logging
set engine.log.debug_level debug

# adjust path accordingly; note that you have to provide the full path to the file
set engine.log.file C:/Scripts/fzprocli.log

# enable more log details
set engine.log.detailed true
set engine.log.raw_listing true

Overriding Prompts

FileZilla Pro Command Line might stop execution to show a prompt asking for confirmation or information.

Use the override prompt settings to override the prompts and provide a predefined response.


Scheduling It on Windows

Once your script runs cleanly by hand, register it with Task Scheduler using schtasks:

schtasks /create /sc DAILY /st 20:00 /tn "Copy files to server" /tr "\"C:\Program Files\FileZilla Pro CLI\fzcli.exe\" --mode standalone --local-path D:\Files --script D:\Scripts\script-file"

This creates a task named "Copy files to server" that runs daily at 8 PM. A few general Windows Task Scheduler practices worth applying here, based on how these jobs typically fail:

  • Use full, quoted, absolute paths for both fzcli.exe and your script file — a relative path that works when you double-click a shortcut can resolve differently under Task Scheduler's own working directory.
  • If the job needs to run whether anyone is logged in or not, set that explicitly in the task's properties and run it under an account that actually has permission to read your local source folder and write to your destination path — a task that "works when I'm logged in" but fails overnight is almost always a permissions or profile issue with the account it's set to run as.
  • As noted above, don't point an unattended task at a master-password-protected Site Manager entry — there's no one there to type the password.

Troubleshooting Quick Reference

My exclude filter isn't skipping the files I expect. Check whether you need --match any instead of the default all, confirm the condition syntax (e.g. name ends .tmp, not name=*.tmp), and remember matching is case-insensitive unless you add --case.

My scheduled task shows as "Running" but nothing happens. Most often this is a master-password prompt waiting for input that will never come, or the task account lacking access to the local or remote path. Test the exact same command manually from a command prompt running as the task's configured account before assuming it's a FileZilla Pro issue. Also verify the return code in Task Scheduler (column "Last Run Result" where 0x0 means that the task completed successfully).

A recursive sync is skipping files inside subdirectories. Check whether --rootonly is set — it restricts filters to the top-level directory only, which is easy to leave on from an earlier command.

Automate With FileZilla Pro CLI

FileZilla Pro CLI is included with every FileZilla Pro and FileZilla Pro Enterprise Server license, for scripted, scheduled, and unattended file transfers.

Tags: , , , , , , , , , , , , , , , , , , ,