使用PERL System()查询路径变量中的空格



我似乎被困在这里。我想通过SSH将系统请求从脚本发送到另一台服务器,检查那里是否存在文件夹。文件夹路径是从另一个脚本传递的,该脚本存储在变量中,并可能具有空间字符。由于我无法用另一个角色替换空间,以避免在" foo bar"之类的文件夹上一个"找不到",所以我需要通过类似的东西 ls '/folderpath/foo bar'到其他服务器的外壳。示例代码看起来像这样:

$cmd = 'ssh -i id_pub $ssh_addr ls $remote_dir'; 
if (system($cmd) == 0) {
do something
}

我已经用尽了所有可能的选项 - 在将传递给命令之前,疲倦了以 逃脱可能的空间,试图将其传递给','',",并在将其传递到$ cmd之前添加两者。但是我总是最终得到这样的事情:

ls folderpathfoo\ bar or ls ' folderpathfoo bar'

,但不是ls 'folderpathfoo bar'

我对Perl不太好,可能有人有经验的人可以推荐解决方法吗?

string :: ShellQuote的shell_quote在构建shell命令中很有用。

my $remote_cmd = shell_quote("ls", "--", $remote_dir);
my $local_cmd = shell_quote("ssh", "-i", "id_pub", $ssh_addr, $remote_cmd);
system($local_cmd);

当然,您可以如下避免在本地的外壳:

use String::ShellQuote qw( shell_quote );
my $remote_cmd = shell_quote("ls", "--", $remote_dir);
system("ssh", "-i", "id_pub", $ssh_addr, $remote_cmd);

运行本地壳并使用它来逃脱命令以使远程外壳安全看起来像这样:

system('env', "ssh_addr=$ssh_addr", "remote_dir=$remote_dir", 'bash', '-c',
       'printf -v remote_cmd "%q " ls -- "$remote_dir"; ssh "$ssh_addr" "$remote_cmd"');

与仅使用"'$remote_cmd'"不同,上述所有可能的值,包括故意恶意的值,只要您的远程外壳也是bash。

感谢 @ikegami的回答,证明了使用选项结束的使用SIGIL --,以确保即使以DASHES开头的remote_dir值也被用ls

好吧,您有几种可能性扩展的可能性。

首先将System()与字符串一起使用。这将破坏您在太空字符上的所有路径。您可以将系统用作列表

解决此问题
system('ssh', '-i', 'id_pub', $ssh_addr, 'ls', $remote_dir)

现在我们仍然有一个问题,因为SSH将在外壳扩展的外壳上运行远程代码,这将破坏空格的路径再次

因此,您需要将$ remote_dir放入'字符中,以阻止远程外壳分解路径:给予

system('ssh', '-i', 'id_pub', $ssh_addr, 'ls', "'$remote_dir'")

希望这有帮助/有效

请注意,正如下面的评论者所说的那样,这是一个假设$ remote_dir中没有'字符。您需要逃脱或解析$ remote_dir,以确保您无法获得看起来像/file.txt'; rm -rf / #的路径,该路径将尝试删除远程系统上的每个文件

让net :: openssh为您照顾一切:

my $ssh = Net::OpenSSH->new($ssh_addr);
$ssh->error and die "unable to connect to remote host: " . $ssh->error;
if ($ssh->test('test', '-d', $remote_dir)) {
   # do something here!
}

哦,看来您在Windows机器上!您可以以类似方式使用Net :: SSH ::任何那里的任何地方。

最新更新