perl - 以编程方式具有特殊字符的scp

标签 perl bash unix ssh scp

我一直在寻找这个问题,但找不到满意的答案。

我有一个 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 另外,老实说,我不确定哪些特殊字符会引起问题,哪些不会引起问题。我想支持所有合法的文件名字符。

最佳答案

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

如下所示,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 ikegami@host.com 'mkdir foo ; touch foo/a foo/b foo/"*" ; ls -1 foo'
*
a
b

$ mkdir foo ; ls -1 foo

$ scp 'ikegami@host.com: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 'ikegami@host.com:foo/\*' foo
*              100%    0     0.0KB/s   00:00

$ ls -1 foo
*

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

相关文章:

bash - 是否可以在 bash 中使用连续的或运算符?

linux - 在 bash 别名中转义字符

linux - Perl脚本: Removing self deplicate rows

regex - Perl正则表达式间隔匹配对应于十六进制数的字符串

linux - 打开和编辑文件对另一个文件也有效

bash - 使用 sed 的条件语句

linux - Linux中模式匹配后提取内容

ruby - 如何从 Unix 命令行与 MS Exchange 日历交互?

linux - 如何在 bash 运行时使用 $ 创建变量值

perl - 在 Perl 正则表达式编译中使用未初始化值