FTP and SFTP clients for Common Lisp
vindarel
Posted on September 28, 2024
You thought all companies would provide well-documented web APIs today? Well, some use a blank .docx and (S)FTP.
For Common Lisp, cl-ftp is one of those libraries that look unmaintained and undocumented, but it works very well, and it is short enough to quickly grab how to use it. It's quite well thought-out, even. It is a pure Lisp library, no system dependencies required.
For example you can do this to send a file:
(ftp:with-ftp-connection (conn :hostname hostname
:username (find-ftp-username)
:password password
:passive-ftp-p t)
(ftp:store-file conn local-filename filename))
You'll have to look at this for more commands: https://github.com/pinterface/cl-ftp/blob/master/simple-client.lisp
we have ftp-shell
, ftp-put
, ftp-list
, ftp-get
, ftp-pwd
, and etc for ls, help, cd, dir.
For SFTP, we must find another means. I didn't find a pure CL library, and it is annoyingly not straightforward to run a SFTP command with a password on the command line. Some solutions exist and I chose lftp. It is included in Debian.
We can run:
lftp sftp://user:password@host -e "put local-file.name; bye"
or better, with the password in an environment variable:
export LFTP_PASSWORD="just_an_example"
lftp --env-password sftp://user@host -e "put local-file.name; bye"
In my scripts I need to handle a connection profile, and even several ones for development, so I ended up with code that I replicate from project to project, hence a new utility:
https://github.com/vindarel/lftp-wrapper
Now do:
CL-USER> (use-package :lftp-wrapper) ;; optional, or:
CL-USER> (uiop:add-package-local-nickname :lftp :lftp-wrapper)
CL-USER> (defvar profile (make-profile-from-plist (uiop:read-file-form "CREDS.lisp-expr"))
#<PROFILE protocol: "sftp", login: "user", port: 10022, server: "prod.com", password? T>
CL-USER> (defvar command (put :cd "I/" :local-filename "data.csv"))
#<PUT cd: "I/", filename: "data.csv" {1007153883}>
CL-USER> (run profile command)
ā¦
success!
We created a profile from credentials on file and from environment variables, we created a command object, and we executed the command for the profile.
We could wrap many more features from lftp. But I follow needs-driven development. So far, it works and it sends my files.
Posted on September 28, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.