Uploading complete directory trees to FTP or SFTP storage supports website deployment, scheduled backups, and bulk data exchange between systems. Consolidating many files into a single transfer step reduces the chance of missing content and keeps deployment and backup workflows predictable. Automated jobs also benefit from a single, repeatable command that can be scheduled or integrated into build pipelines.

The cURL tool acts as a general-purpose URL transfer client for protocols such as FTP, FTPS, and SFTP. For uploads, it sends file data to a URL formed from a scheme (ftp:// or sftp://), hostname, credentials, and a remote path. Raw directory uploads are not a native feature of these protocols, so a directory is typically packed into an archive first, then uploaded as a single file that the remote system later unpacks.

Large directory uploads can overwrite live content, exceed storage quotas, or saturate network links when sent to the wrong location or with incorrect paths. Credentials placed directly in the command line appear in shell history and process listings on multiuser systems, which can leak passwords. Safer workflows rely on restricted accounts, key-based SFTP access, and test uploads into non-critical directories before replacing production data.

Steps to upload directories to FTP or SFTP with cURL:

  1. Check the installed cURL version and protocol support from a terminal on Linux.
    $ curl --version
    curl 8.5.0 (aarch64-unknown-linux-gnu) libcurl/8.5.0 OpenSSL/3.0.13 zlib/1.3 brotli/1.1.0 zstd/1.5.5 libidn2/2.3.7 libpsl/0.21.2 (+libidn2/2.3.7) libssh/0.10.6/openssl/zlib nghttp2/1.59.0 librtmp/2.3 OpenLDAP/2.6.7
    Release-Date: 2023-12-06, security patched: 8.5.0-2ubuntu10.6
    Protocols: dict file ftp ftps gopher gophers http https imap imaps ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
    Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd
    ##### snipped #####

    Presence of ftp, ftps, and sftp in the Protocols line confirms that FTP and SFTP uploads are available through cURL without additional components.

  2. Move to the parent directory that contains the folder intended for upload.
    $ cd /work
    $ ls -d other-data project
    other-data
    project

    Running commands from the parent directory keeps the archive contents relative (for example, starting at project) instead of embedding an entire absolute path inside the compressed file.

  3. Create a compressed archive that represents the entire directory tree as a single file.
    $ tar --create --gzip --file project-2025-12-archive.tar.gz project/
    $ ls -d other-data project project-2025-12-archive.tar.gz
    other-data
    project
    project-2025-12-archive.tar.gz

    The file project-2025-12-archive.tar.gz now contains the full project directory including subdirectories and regular file metadata, and can be transferred in a single upload operation.

  4. Upload the archive to an FTP server using an authenticated ftp:// URL.
    $ curl --upload-file project-2025-12-archive.tar.gz --user user:password ftp://ftp.example.net/project-2025-12-archive.tar.gz

    Adding a password directly to --user user:password or embedding it in the URL exposes credentials in shell history and process listings; safer patterns use password prompts, locked-down .netrc files, or limited-purpose accounts.

  5. Send the same archive over SFTP when encrypted transport or key-based authentication is required.
    $ curl --upload-file project-2025-12-archive.tar.gz --user user:password sftp://sftp.example.net/home/user/project-2025-12-archive.tar.gz

    SFTP operates over SSH, so authentication methods such as SSH keys and agents apply, and the default remote directory is usually the SSH account’s home directory rather than a web document root.

  6. Allow cURL to create missing intermediate FTP directories when targeting a nested path.
    $ curl --ftp-create-dirs --upload-file project-2025-12-archive.tar.gz --user user:password ftp://ftp.example.net/releases/2025/12/project-2025-12-archive.tar.gz

    The --ftp-create-dirs option affects only FTP URLs; directories for SFTP targets normally must be created separately with SSH commands or deployment tooling before uploading.

  7. Confirm that the archived directory file exists on the remote server by listing the upload location.
    $ curl --silent --user user:password ftp://ftp.example.net/releases/2025/12/
    -rw-------    1 1001     1001          162 Jan 10 06:13 project-2025-12-archive.tar.gz
    $ curl --silent --user user:password sftp://sftp.example.net/home/user/
    ##### snipped #####
    -rw-r--r--    1 user     user          162 Jan 10 06:13 project-2025-12-archive.tar.gz
    ##### snipped #####

    Appearance of project-2025-12-archive.tar.gz with the expected size and a recent timestamp indicates that the directory upload archive reached the remote system successfully and is ready to be unpacked there.