我已经尝试了几个小时来弄清楚如何让 perl 进入scp
名称中带有空格的目录。我目前收到错误
scp: ambiguous target
这是不起作用的脚本:
#!/usr/bin/perl
# Assuming you already have passwordless ssh setup from some account to root on HOST
# On HOST, setup test files and directories
# root@HOST$ mkdir /tmp/from/spaced\ mydir
# root@HOST$ touch /tmp/from/spaced\ mydir/t1
# root@HOST$ mkdir /tmp/to
my $HOST='localhost';
my $escaped_component_name = 'spaced mydir';
# try to form scp from-arg that will preserve the space
# in the directory name by escaping whitespace with backslash
$escaped_component_name =~ s/(\s)/\\$1/g;
my $scp_from = '/tmp/from/'.$escaped_component_name.'/*';
my $scp_to = '/tmp/to/'.$escaped_component_name;
system 'scp', '-vr', '--', 'root@'.$HOST.':'.$scp_from, 'root@'.$HOST.':'.$scp_to;
有人看到我做错了什么吗?
答案1
我究竟做错了什么?
使用system
。这将分叉一个 shell,并将其余参数作为选项。换句话说,sh
就是吃引用。
尝试:
system 'scp', '-vr', '--', '"root@'.$HOST.':'.$scp_from.'"', '"root@'.$HOST.':'.$scp_to.'"' ;`
答案2
首先,您确定scp
支持远程到远程传输吗?据我所知,有些版本是通过开关来实现的-3
。
不管怎样,每当我遇到参数问题时,我都会把这个脚本放在手边:
#!/usr/bin/perl
my $count;
for (@ARGV) {
s/([\x00-\x1F\x7F])/'\x'.unpack('H*',$1)/ge;
printf "%d: '%s'\n", ++$count, $_;
}
让我们试试你的代码:
$ perl
my $HOST='localhost';
my $escaped_component_name = 'spaced mydir';
# try to form scp from-arg that will preserve the space
# in the directory name by escaping whitespace with backslash
$escaped_component_name =~ s/(\s)/\\$1/g;
my $scp_from = '/tmp/from/'.$escaped_component_name.'/*';
my $scp_to = '/tmp/to/'.$escaped_component_name;
system 'sandbox/args.pl', '-vr', '--', 'root@'.$HOST.':'.$scp_from, 'root@'.$HOST.':'.$scp_to;
# (Control-D)
1: '-vr'
2: '--'
3: 'root@localhost:/tmp/from/spaced\ mydir/*'
4: 'root@localhost:/tmp/to/spaced\ mydir'
是的,转义很好 - 我的版本scp
需要目标路径中的反斜杠(但不在本地路径中);我想这与ssh
幕后运作有关。
让我们用真实的东西来尝试一下:
$ perl
$local_dir = "some dir/";
$remote_dir = "/tmp/some dir/";
$remote_dir =~ s/(\s)/\\$1/g;
system 'scp', $local_dir."login.sql", 'user@host:'.$remote_dir;
# (Control-D)
login.sql 100% |********************************************| 434 00:00
答案3
这是对我有用的最终脚本。感谢@Ricky Beam 和@arielCo 的意见。使用文件::规范;
my $escaped = $component_name;
$escaped =~ s/(\s)/\\$1/g;
# scp-from-path
my $scp_from = File::Spec->catdir($REMOTE_MV_HOME, $escaped,'*');
# scp-to-path
my $scp_to = File::Spec->catdir($REMOTE_MV_HOME, $escaped, '\.');
# use double-quotes on only the to-path because
# of the double-shelling (local fork of 'sh' and then the remote execution 'sh')
system 'scp', '-vr', '--', 'root@'.$HOST.':'.$scp_from, 'root@'.$HOST.':"'.$scp_to.'"' ;