2

Я пытаюсь использовать ImageMagick из командной строки в Windows 7, чтобы конвертировать много изображений одновременно. Я хотел бы использовать опцию -set, но получаю неожиданные результаты. Короткий пример некоторых странностей, которые я вижу, таков:

C:\>convert example.jpg -verbose -set filename:foo hello -set filename:bar world "%[filename:foo]_%[filename:bar].png"
example.jpg=>helloworld.png JPEG 352x264 352x264+0+0 8-bit DirectClass 131KB 0.125u 0:00.135

Обратите внимание, что символ подчеркивания загадочным образом удаляется из выходного имени файла. Я могу использовать символ вставки (^), чтобы избежать второго знака процента, чтобы сохранить подчеркивание:

C:\>convert example.jpg -verbose -set filename:foo hello -set filename:bar world "%[filename:foo]_^%[filename:bar].png"
example.jpg=>hello_world.png JPEG 352x264 352x264+0+0 8-bit DirectClass 131KB 0.125u 0:00.126

Что тут происходит? Почему вставка каретки приводит к сохранению подчеркивания? Является ли каретка (^) даже правильным побегом? Это происходит из-за расширения переменной среды командной оболочки или странность возникает из-за того, как ImageMagick обрабатывает экранирование процентов? В любом случае, существуют ли общие принципы использования символов процента в аргументах командной строки, которым можно следовать, чтобы вызвать предсказуемое поведение?

То, что я на самом деле хочу сделать, - это версия вышеупомянутой команды с множеством установленных свойств, которая может обрабатывать самые имена файлов со специальными символами, такими как пробелы и символы процента, но кажется глупым пытаться сделать это, если я не могу понять этот гораздо более простой пример , В конечном итоге мне нужно будет выполнить команду из программы .NET.

Я просмотрел http://www.robvanderwoude.com/escapechars.php и Escaping %'s в file-/folder-names в командной строке, но не смог понять, как применить совет к моей проблеме.

Обновить

Добавим еще несколько примеров для ответов на вопросы в комментариях @dbenham и @Synetech.

Перемещение подчеркивания от перед вторым символом процента, как в последнем примере выше, до подчеркивания приводит к созданию файла с именем hello^world.png:

C:\>convert example.jpg -verbose -set filename:foo hello -set filename:bar world "%[filename:foo]^_%[filename:bar].png"
example.jpg=>hello^world.png JPEG 352x264 352x264+0+0 8-bit DirectClass 131KB 0.141u 0:00.132

Выход из каретки в окружающих кавычках всегда приводит к helloworld.png , независимо от того, где размещены каретки внутри:

C:\>convert example.jpg -verbose -set filename:foo hello -set filename:bar world ^"^%[filename:foo]_^%[filename:bar].png^"
example.jpg=>helloworld.png JPEG 352x264 352x264+0+0 8-bit DirectClass 131KB 0.109u 0:00.115

C:\>convert example.jpg -verbose -set filename:foo hello -set filename:bar world ^"%[filename:foo]_^%[filename:bar].png^"
example.jpg=>helloworld.png JPEG 352x264 352x264+0+0 8-bit DirectClass 131KB 0.141u 0:00.143

C:\>convert example.jpg -verbose -set filename:foo hello -set filename:bar world ^"^%[filename:foo]_%[filename:bar].png^"
example.jpg=>helloworld.png JPEG 352x264 352x264+0+0 8-bit DirectClass 131KB 0.125u 0:00.126

C:\>convert example.jpg -verbose -set filename:foo hello -set filename:bar world ^"%[filename:foo]_%[filename:bar].png^"
example.jpg=>helloworld.png JPEG 352x264 352x264+0+0 8-bit DirectClass 131KB 0.125u 0:00.131

C:\>convert example.jpg -verbose -set filename:foo hello -set filename:bar world ^"%[filename:foo]^_%[filename:bar].png^"
example.jpg=>helloworld.png JPEG 352x264 352x264+0+0 8-bit DirectClass 131KB 0.125u 0:00.111

1 ответ1

3

Я не могу объяснить странное поведение, которое вы видите. Кажется, что это результат обработки процентов cmd.exe, но, насколько я понимаю, он не совсем соответствует поведению cmd.exe.

Сбросить проценты в пакетном файле легко - просто удвойте их. Но это не работает из командной строки. Технически, нет способа избежать процента в командной строке Windows cmd.exe.

Командная строка может расширить проценты одним из двух способов:

1) Разверните переменные окружения.

Если текст между двумя процентами соответствует имени переменной среды, тогда конструкция процента заменяется значением.

C:\test>set test=hello

C:\test>echo %test%
hello

Если текст в процентах не совпадает с именем переменной среды, то полный исходный текст сохраняется.

C:\test>echo %notDefined%
%notDefined%

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

C:\test>echo ^%test^%
%test%

Но это на самом деле не ускользает от процентов. Вместо этого он ищет переменную с именем test^ и не находит ее. Таким образом, оригинальный текст не нарушен. Затем каретки удаляются во время обычной побег обработки. Это можно доказать, определив переменную с кареткой в имени.

C:\test>set "test^=goodbye"

C:\test>echo ^%test^%
goodbye

Каретка до первого процента ничего не делает. Вы можете поместить каретку в любом месте между процентами, и это предотвратит расширение переменной до тех пор, пока не существует переменной с кареткой в имени.

C:\test>echo %te^st%
%test%

Если текст указан в кавычках, то каретка не будет удалена, если кавычки также не экранированы.

C:\test>echo "%te^st%"
"%te^st%"

C:\test>echo ^"te^st%^"
"%test%"

Ситуация немного сложнее, когда есть двоеточия. Двоеточие используется раскрытием переменной для операций подстановки и подстроки. Имя переменной - это текст между первым процентом и двоеточием.

C:\test>echo %test:el=a%
halo

C:\test>echo %test:~1,2%
el

Если текст между первым процентом и двоеточием не совпадает с именем переменной, или если текст между двоеточием и последним процентом не является допустимой конструкцией подстановки или подстроки, то исходный текст сохраняется без подстановки.

C:\test>echo %test:1,2%
%test:1,2%

Этот последний пример больше всего напоминает вашу ситуацию. Текст между вашим первым процентом и двоеточием не соответствует переменной, а текст между двоеточием и последним процентом не является конструкцией подстановки или подстроки, поэтому следует сохранить всю конструкцию, включая подчеркивание.По этой причине я не вижу, как cmd.exe может лишить вас подчеркивания. Но тот факт, что добавление каретки перед вторым процентом сохраняет подчеркивание, вызывает у меня подозрение. Мне бы очень хотелось знать, что произойдет, если вместо этого вы передвинете каретку перед подчеркиванием.


2) Развернуть для переменных

Не проблема в вашем случае, но проценты могут также вызвать проблемы, если действует цикл FOR. В этом случае нет способа защитить процент с помощью каретки, потому что каретка удаляется перед расширением переменной FOR. В этом примере я хочу, чтобы выходные данные читали %A=1 , но это не работает.

C:\test>for %A in (1 2) do @echo ^%^A=%A
1=1
2=2

Самый удобный способ защитить процент - это ввести другую переменную FOR

C:\test>for %C in (%) do @for %A in (1 2) do @echo %CA=%A
%A=1
%A=2

Это работает так же хорошо, чтобы поместить A в другую переменную

C:\test>for %C in (A) do @for %A in (1 2) do @echo %%C=%A
%A=1
%A=2

Обновить

Хороший способ проверить, где подчеркивание снимается, - поставить ECHO перед вашей командой. Если исходная команда сохраняется с подчеркиванием, то вы знаете, что виновником должна быть утилита преобразования.

C:\>echo convert example.jpg -verbose -set filename:foo hello -set filename:bar world "%[filename:foo]_%[filename:bar].png"

Подчеркивание сохраняется на моей машине :-)


Если вас больше интересует, как работает анализатор команд, см. Https://stackoverflow.com/a/4095133/1012053. Этот ответ в основном относится к пакетному разбору, но правила очень похожи, и в конце кратко описываются основные различия.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .