Командная строка Windows ImageMagick процентные экраны

Командная строка Windows ImageMagick процентные экраны

Я пытаюсь использовать 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иЭкранирование % в именах файлов/папок в командной строкено не мог понять, как применить этот совет к моей проблеме.

Обновлять

Добавляю еще несколько примеров в ответ на вопросы в комментариях от @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

Я не могу объяснить странное поведение, которое вы видите. Похоже, что это результат обработки процентов 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. В этом случае нет способа защитить проценты с помощью каретки, поскольку каретка удаляется до расширения переменной 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 перед командой. Если исходная команда сохраняется с подчеркиванием, то вы знаете, что виновата утилита convert.

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. Этот ответ в основном касается пакетного анализа, но правила очень похожи, а раздел в конце кратко описывает основные различия.

Связанный контент