这个问题找了好久,没有找到满意的答案。

我有一个 perl 脚本,需要将文件从一台主机复制到另一台主机,本质上

sub copy_file{
    my($from_server, $from_path, $to_server, $to_path, $filename) = @_;

    my $from_location = "$from_server:\"\\\"${from_path}${filename}\\\"\"";
    my $to_location = $to_path . $filename;
    $to_location =~ s/\s/\\\\ /g;
    $to_location = "${to_server}:\"\\\"${to_location}\\\"\"";

    return system("scp -p $from_location $to_location >/dev/null 2>&1"");
}

问题是,我的一些文件名如下所示:
BLAH;BLAH;BLAH.TXT
Some really nicely named file( With spaces, prentices, &, etc...).xlx

我已经在处理空格了,它的代码非常难看,因为在每一方,文件可以是本地的或远程的,并且转义对于 scp 调用的 from 和 to 部分是不同的。

我真正想要的是要么以某种方式转义所有可能的特殊字符,要么通过使用 POSIX 系统调用以某种方式完全绕过 shell 扩展。如果需要,我可以编写 XS 模块。

我在 .ssh 目录中设置了正确的 key
此外,我也不确定哪些特殊字符会和不会引起问题。我想支持所有合法的文件名字符。

最佳答案

假设您想使用 foo(s) 复制文件 scp

如下所示,scp 将源和目标视为 shell 文字,因此您将以下参数传递给 scp :

  • scp
  • -p
  • --
  • host1.com:foo\(s\)host1.com:'foo(s)'
  • host2.com:foo\(s\)host2.com:'foo(s)'

  • 您可以使用 system 的多参数语法加上转义函数来做到这一点。
    use String::ShellQuote qw( shell_quote );
    
    my $source = $from_server . ":" . shell_quote("$from_path/$filename");
    my $target = $to_server   . ":" . shell_quote("$to_path/$filename");
    
    system('scp', '-p', '--', $source, $target);
    

    如果你真的想构建一个 shell 命令,像往常一样使用 shell_quote
    my $cmd = shell_quote('scp', '-p', '--', $source, $target);
    
    $ ssh [email protected] 'mkdir foo ; touch foo/a foo/b foo/"*" ; ls -1 foo'
    *
    a
    b
    
    $ mkdir foo ; ls -1 foo
    
    $ scp '[email protected]:foo/*' foo
    *              100%    0     0.0KB/s   00:00
    a              100%    0     0.0KB/s   00:00
    b              100%    0     0.0KB/s   00:00
    
    $ ls -1 foo
    *
    a
    b
    
    $ rm foo/* ; ls -1 foo
    
    $ scp '[email protected]:foo/\*' foo
    *              100%    0     0.0KB/s   00:00
    
    $ ls -1 foo
    *
    

    关于perl - 以编程方式带有特殊字符的 scp,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22948664/

    10-14 18:48