Home > linux, voodoo > Remote copy without scp

Remote copy without scp

April 1st, 2009 rbu

I often need to copy small files (configs, scripts, patches) from one machine to another and I have found using “cat” and copy-paste to be very unreliable for this: You lose tab characters, file names, permissions, and it cannot handle binaries. Plus, it gets tedious for long text files. So I added a function to my .zshrc that takes file names as an argument and prints shell code you can simply copy and paste into a remote ssh session. The current working directory will then contain the files:

rbu@localhost ~/copy-example $ ls -l
total 8.0K
-rw-r--r-- 1 rbu rbu  29 2009-04-01 17:24 doc1
-rwx--x--x 1 rbu rbu 181 2009-04-01 17:25 some-bin

rbu@localhost ~/copy-example $ copy doc1 some-bin
cat<<E=O=F | perl -MMIME::Base64 -e 'print MIME::Base64::decode(join("", <>))' - | tar xj
QlpoOTFBWSZTWbDjvy4AANl///6/SH1QLn+oZAgORH7jngCAcExyZEJgBABAYABqMEQJMAEbbbMN
QKR5TaEwAn6oxGaGiYAQDCNPTSY9QmTT0AaptKbUxGhHoaAE0aY0AAAEMJowEYTJglEinqD1Mgeo
ZGagAHqM0RkyNAD1D1PUADynlMBeffJ2xSkqIiZOGCIOv87QvSzIWsqS1GG4qIB55xMGD5cgy2Ya
IgH0wmmgmcKCEZJL0BilCat4n/ubxlVIXfIgMCABOZxo2zA0pK5IxR1+ikXrUe7bmHxeL1jyK6fe
fcO0xLbzPXYIxokkI+yKJynt03pqRDZQfBMbvdEaBRQwjQZvEhdVNDcIAOAhVyeeaKerlMFSJYBM
56ibgEosooEIAO8PC9oAbQmOVk8YoGRBgkN9wH8oaOxCgeCuu6VCljLtzvDSGdIYGcPOgRVh+LBi
u/AotDOnl/uuQtH7Md37RU6SE4jjPOLUEHLj0OIOKTNkqk1FiehcQSg62CAQ/4u5IpwoSFhx35cA
E=O=F

On the remote host you can simply paste this code:

buchholz@remotehost:~/target-dir$ ls -l
total 0
buchholz@remotehost:~/target-dir$ cat<<E=O=F | \
   perl -MMIME::Base64 -e 'print MIME::Base64::decode(join("", <>))' - | tar xj
> QlpoOTFBWSZTWbDjvy4AANl///6/SH1QLn+oZAgORH7jngCAcExyZEJgBABAYABqMEQJMAEbbbMN
> QKR5TaEwAn6oxGaGiYAQDCNPTSY9QmTT0AaptKbUxGhHoaAE0aY0AAAEMJowEYTJglEinqD1Mgeo
> ZGagAHqM0RkyNAD1D1PUADynlMBeffJ2xSkqIiZOGCIOv87QvSzIWsqS1GG4qIB55xMGD5cgy2Ya
> IgH0wmmgmcKCEZJL0BilCat4n/ubxlVIXfIgMCABOZxo2zA0pK5IxR1+ikXrUe7bmHxeL1jyK6fe
> fcO0xLbzPXYIxokkI+yKJynt03pqRDZQfBMbvdEaBRQwjQZvEhdVNDcIAOAhVyeeaKerlMFSJYBM
> 56ibgEosooEIAO8PC9oAbQmOVk8YoGRBgkN9wH8oaOxCgeCuu6VCljLtzvDSGdIYGcPOgRVh+LBi
> u/AotDOnl/uuQtH7Md37RU6SE4jjPOLUEHLj0OIOKTNkqk1FiehcQSg62CAQ/4u5IpwoSFhx35cA
> E=O=F
buchholz@remotehost:~/target-dir$ ls -l
total 8
-rw-r--r-- 1 buchholz buchholz  29 Apr  1 17:24 doc1
-rwx--x--x 1 buchholz buchholz 181 Apr  1 17:25 some-bin

And now for the shell action to do this (in ZSH):

function copy() {
        STR=$(tar cj $@ | perl -MMIME::Base64 -e 'print MIME::Base64::encode(join("", <>))' \
            - ; exit $pipestatus[1] ) || return $?
        echo "cat<<E=O=F | perl -MMIME::Base64 -e \
             'print MIME::Base64::decode(join(\"\", <>))' - | tar xj"
        echo "$STR"
        echo "E=O=F"
}

If you are using bash, you need to replace “exit $pipestatus[1]” with “exit $PIPESTATUS” :-/

Categories: linux, voodoo Tags:
  1. Tannek
    April 1st, 2009 at 18:08 | #1

    I didn’t get the joke… / :

  2. April 1st, 2009 at 20:54 | #2

    Ah, how glad I am to finally read something sane on April’s Fool ;)

    Thanks, it’s very nice, actually.

    Hope you meant it as a joke, so I look stupid now =)

  3. Robin H Johnson
    April 1st, 2009 at 23:25 | #3

    I use similar stuff often enough, esp when I’ve had to bounce through multiple layers of firewall with SSH.

    encode:
    # tar cj . | base64
    decode:
    # base64 -d | tar xj

Comments are closed.