Automatic file transfer in iTerm2 via ZModem

scp is a great way to securely transfer files from computer to computer, but wouldn’t it be nice if you could just automatically send files over the existing SSH connection you’ve already opened?

Back in the days of modem-based BBSes and dial-up machine access, file transfers were forced to run over the same TTY as your interaction with the system. A number of different solutions evolved for this, starting with the grandfather of transfer solutions, XModem. Other transfer protocols evolved, some starting from the ground up like Kermit, while YModem and ZModem build on the foundation of XModem.

The latest version of iTerm 2 added support for two features that were very interesting: Triggers, that match a regular expression to a line of text; and co-processes, that can feed input directly into a terminal. With these two features, we can add the ability to stream files to and from any server over an existing ssh session. As ZModem is most modern protocol with wide support (lrzsz is well-supported and packaged on both OSX and Linux), I’ll show you how to use it to automate piggy-backed file uploads and downloads in your iTerm sessions.

Setup

First of all, install lrzsz via brew. This will install the sz and rz binaries in /usr/local/bin/:

macbook-pro-2:~ matthew$ brew install lrzsz
==> Downloading http://www.ohse.de/uwe/releases/lrzsz-0.12.20.tar.gz
==> ./configure --prefix=/usr/local/Cellar/lrzsz/0.12.20 --mandir=/usr/local/Cellar/lrzsz/0.12.20/share/man
==> make
==> make install
/usr/local/Cellar/lrzsz/0.12.20: 13 files, 376K, built in 21 seconds

Secondly, grab the scripts from my iterm2-zmodem github repo, and save them in /usr/local/bin/.

Next, we’ll add a Trigger to your iTerm 2 profile that will trigger on the signature of the rz and sz commands. The setup for these commands differs based on the iTerm 2 version you have:

Build newer than 1.0.0.20111026

    Regular expression: \*\*B0100
    Action: Run Coprocess
    Parameters: /usr/local/bin/iterm2-send-zmodem.sh

    Regular expression: \*\*B00000000000000
    Action: Run Coprocess
    Parameters: /usr/local/bin/iterm2-recv-zmodem.sh

Build older than 1.0.0.20111026 (only receive supported)

    Regular expression: [\$#] rz( -v)?$
    Action: Run Coprocess
    Parameters: /usr/local/bin/iterm2-send-zmodem.sh

Note: ideally we’d be matching on the ZModem initial packet signature: \*\*\u0018B01 in all versions of iTerm 2, but earlier versions of iTerm 2 had a bug that broke this pattern detection in this case. Instead we’re matching against the pattern of the rz command typed at a shell for those older builds.

Receiving files from the server

To receive a file on your server, type the following at a shell prompt:

# rz

A file-picker dialog will then pop up asking you for the file to send. Once you choose the file to send, it will automatically transfer the file across your existing console session.

Sending files to the server

To send files from your server to your desktop, type the following:

# sz file1 file2 file3 /folder/file*

A folder picker will show up, asking where you want to drop the files. If you send multiple files, they will all appear in this folder.

Wrap-up

This is a pretty rough first pass at this, but the shell scripts are available on github if you’ve got ideas for improvement.

Comments: discuss this on Hacker News

Comments are closed.