Search code examples
perlsshescapingrsyncnon-ascii-characters

Escaping bad server paths for RSYNC via SSH


I have a client using the most ridiculous file/folder naming, and need to RSYNC their data to a NAS. My RSYNC logic is written in Perl, and quotemeta() worked well, until we had to deal with Danish characters.

See example code:

#!/usr/bin/env perl
$my_string_a = "/data/stuff/folder K/ \snappy/SLE.T.TET/Div (erse)/SLETTET/Disk klæbere";
$my_string_b = quotemeta($my_string_a);
print "\n".$my_string_a."\n".$my_string_b."\n";
exit;

Outputs:

/data/stuff/folder K/ snappy/SLE.T.TET/Div (erse)/SLETTET/Disk klæbere
\/data\/stuff\/folder\ K\/\ snappy\/SLE\.T\.TET\/Div\ \(erse\)\/SLETTET\/Disk\ kl\�\�bere

Note: I have to use escape characters as ssh / rsync requires "double escaping" in Perl.

Is there a better canned solution or will I need to Regex my way past this?


Solution

  • Perl builtins invoking external programs (i.e. system, exec, etc.) don't always handle encodings correctly.

    You can try using Net::OpenSSH which has native support for transferring files with rsync and can handle automatic quoting and encoding of the rsync command line for you.

    use Net::OpenSSH;
    use utf8;
    
    my $ssh = Net::OpenSSH->new(...,
                                argument_encoding => 'utf8');
    
    $ssh->rsync_put("/data/stuff/folder K/ \snappy/SLE.T.TET/Div (erse)/SLETTET/Disk klæbere",
                    $target_dir)
        or die "rsync_failed " . $ssh->error;