我一直在寻找这个问题,但找不到满意的答案。
我有一个 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/