Использовать переменную с пробелом Perl

В настоящее время я работаю над проектом, но у меня есть одна большая проблема. У меня есть картинка с пробелом в названии, и я хочу сделать монтаж. Проблема в том, что я не могу переименовать свою фотографию, и мой код выглядит так:

$pic1 = qq(picture one.png);
$pic2 = qq(picture two.png);

my $cmd = "C:\...\montage.exe $pic1 $pic2 output.png";

system($cmd);

но из-за пробелов montage.exe не работает. Как я могу выполнить свой код без переименования всех моих картинок?

Большое спасибо за ответ!

4 ответа

Вы можете правильно указывать имена файлов в строке, которую вы передаете системе, как показывает @Borodin в своем ответе. Что-то вроде: system("montage.exe '$pic1' '$pic2'")

Однако более надежным и безопасным решением является передача аргументов в montage.exe в качестве дополнительных параметров в системном вызове:

system('montage.exe', $pic2, $pic2, 'output.png')

Теперь вам не нужно беспокоиться о вложении правильных кавычек или о файлах с неожиданными символами. Это не только более простой код, но и позволяет избежать проблем со злонамеренным внедрением, если эти имена файлов когда-либо поступают из испорченного источника. Кто-то может войти | rm *, но ваш системный вызов не удалит все ваши файлы для вас.

Кроме того, в реальной жизни у вас, вероятно, не будет отдельной скалярной переменной для каждого имени файла. Вы будете иметь их в массиве. Это делает ваш системный вызов еще проще:

system('montage.exe', @filenames, 'output.png')

Это не только очень просто, но и позволяет избежать ловушки слишком длинной командной строки. Если ваши имена файлов имеют хорошие длинные пути (возможно, 50-100 символов), командная строка Windows превысит максимальную длину команды после примерно 100 файлов. Передача аргументов через system() вместо одной большой строки устраняет это ограничение.

В качестве альтернативы вы можете передать аргументы в montage.exe в виде списка (вместо того, чтобы объединить их все в строку):

use strict;
use warnings;

my $pic1 = qq(picture one.png);
my $pic2 = qq(picture two.png);

my @cmd = ("C:\...\montage.exe", $pic1, $pic2, "output.png");

system(@cmd);

Вы должны поместить кавычки вокруг имен файлов, которые имеют пробелы. Вы также должны избежать обратной косой черты

my $cmd = qq{C:\\...\\montage.exe "$pic1" "$pic2" output.png};

В системах Unix лучшим подходом является форма с несколькими аргументами system потому что 1) он избегает вызова оболочки и 2) это формат, принятый вызовом ОС. Ни один из них не верен в Windows. Вызов ОС для запуска программы ожидает командную строку, и systemПопытка сформировать эту командную строку иногда неверна. Самый безопасный подход - использовать Win32:: ShellQuote.

use Win32::ShellQuote qw( quote_system );

system quote_system("C:\\...\\montage.exe", $pic1, $pic2, "output.png");
Другие вопросы по тегам