The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Net::SSH::Any::POSIXShellQuoter;

my $noquote_class = '\\w/\\-=@';
my $glob_class    = '*?\\[\\],{}:!.^~';

sub quote {
    shift;
    my $quoted = join '',
	map { ( m|^'$|                  ? "\\'"  :
		m|^[$noquote_class]*$|o ? $_     :
		"'$_'" ) } split /(')/, $_[0];
    length $quoted ? $quoted : "''";
}

sub quote_glob {
    shift;
    my $arg = shift;
    my @parts;
    while ((pos $arg ||0) < length $arg) {
	if ($arg =~ m|\G'|gc) {
	    push @parts, "\\'";
	}
	elsif ($arg =~ m|\G([$noquote_class$glob_class]+)|gco) {
	    push @parts, $1;
	}
	elsif ($arg =~ m|\G(\\[$glob_class\\])|gco) {
	    push @parts, $1;
	}
	elsif ($arg =~ m|\G\\|gc) {
	    push @parts, '\\\\'
	}
	elsif ($arg =~ m|\G([^$glob_class\\']+)|gco) {
	    push @parts, "'$1'";
	}
	else {
	    require Data::Dumper;
	    $arg =~ m|\G(.+)|gc;
	    die "Internal error: unquotable string:\n". Data::Dumper::Dumper($1) ."\n";
	}
    }
    my $quoted = join('', @parts);
    length $quoted ? $quoted : "''";
}

1;