A porcentagem do ImageMagick da linha de comando do Windows escapa

A porcentagem do ImageMagick da linha de comando do Windows escapa

Estou tentando usar o ImageMagick na linha de comando do Windows 7 para converter muitas imagens de uma vez. Gostaria de usar a interface da opção -set, mas estou obtendo resultados inesperados. Um pequeno exemplo de algumas das estranhezas que estou vendo é este:

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

Observe que o caractere de sublinhado é misteriosamente excluído do nome do arquivo de saída. Posso usar um sinal de intercalação (^) para escapar do segundo sinal de porcentagem e reter o sublinhado:

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

O que está acontecendo aqui? Por que a inserção do sinal de intercalação faz com que o sublinhado seja retido? O sinal de intercalação (^) é o escape correto para tentar? Esse comportamento é devido à expansão da variável de ambiente do shell de comando ou a estranheza resulta da maneira como o ImageMagick lida com os escapes percentuais? De qualquer forma, existem princípios gerais relativos ao uso de símbolos de porcentagem em argumentos de linha de comando que podem ser seguidos para causar um comportamento previsível?

O que eu realmente quero fazer é uma versão do comando acima com muito mais propriedades definidas, que possa lidar com muitos nomes de arquivos com caracteres especiais como espaços e símbolos de porcentagem, mas parece tolice tentar isso se não consigo entender este exemplo muito mais simples . Por fim, precisarei executar o comando em um programa .NET.

eu olheihttp://www.robvanderwoude.com/escapechars.phpeEscapando% de nomes de arquivos/pastas na linha de comandomas não consegui descobrir como aplicar o conselho ao meu problema.

Atualizar

Adicionando mais alguns exemplos para responder perguntas nos comentários de @dbenham e @Synetech.

Mover o sublinhado antes do segundo símbolo de porcentagem, como no último exemplo acima, para antes do sublinhado, produz um arquivo chamado 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

O escape de circunflexo das aspas ao redor sempre resulta em helloworld.png, independentemente de onde os circunflexos são colocados:

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

Responder1

Não consigo explicar o comportamento estranho que você está vendo. Quase parece que é o resultado do processamento percentual do cmd.exe, mas não corresponde exatamente ao comportamento do cmd.exe, pelo que entendi.

É fácil escapar de porcentagens em um arquivo em lote - basta dobrá-las. Mas isso não funciona na linha de comando. Tecnicamente, não há como escapar de uma porcentagem na linha de comando do Windows cmd.exe.

A linha de comando pode expandir porcentagens de duas maneiras:

1) Expanda Variáveis ​​de ambiente.

Se o texto entre duas porcentagens corresponder ao nome de uma variável de ambiente, a construção de porcentagem será substituída pelo valor.

C:\test>set test=hello

C:\test>echo %test%
hello

Se o texto entre as porcentagens não corresponder ao nome de uma variável de ambiente, o texto original completo será retido.

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

A própria documentação da Microsoft afirma que você pode escapar da porcentagem colocando um sinal de intercalação na frente.

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

Mas isso não significa realmente escapar da percentagem. Em vez disso, ele está procurando uma variável chamada test^e não a encontra. Portanto, o texto original não foi perturbado. Em seguida, os sinais de intercalação são removidos durante o processamento normal de escape. Isso pode ser comprovado definindo uma variável com o sinal de intercalação no nome.

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

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

O sinal de intercalação antes do primeiro por cento não faz nada. Você pode colocar um sinal de intercalação em qualquer lugar entre as porcentagens e isso impedirá a expansão da variável, desde que não exista nenhuma variável com o sinal de intercalação no nome.

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

Se o texto estiver entre aspas, o acento circunflexo não será eliminado, a menos que as aspas também sejam escapadas.

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

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

A situação é um pouco mais complicada quando há dois pontos. Os dois pontos são usados ​​pela expansão de variáveis ​​para operações de substituição e substring. O nome da variável é o texto entre o primeiro percentual e os dois pontos.

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

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

Se o texto entre o primeiro percentual e os dois pontos não corresponder a um nome de variável, ou se o texto entre os dois pontos e o último percentual não for uma substituição válida ou uma construção de substring, o texto original será preservado sem substituição.

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

Este último exemplo se parece mais com a sua situação. O texto entre o primeiro percentual e os dois pontos não corresponde a uma variável, e o texto entre os dois pontos e o último percentual não é uma substituição ou construção de substring,então toda a construção deve ser preservada,incluindo o sublinhado. Por esse motivo, não vejo como o cmd.exe poderia estar eliminando seu sublinhado.Mas o fato de adicionar um acento circunflexo antes do segundo por cento preserva o sublinhado me deixa desconfiado. Eu realmente gostaria de saber o que acontece se você mover o cursor antes do sublinhado.


2) Expanda variáveis ​​FOR

Não é um problema no seu caso, mas as porcentagens também podem causar problemas se um loop FOR estiver em vigor. Não há como proteger a porcentagem usando um sinal de intercalação neste caso, porque o sinal de intercalação é removido antes da expansão da variável FOR. Neste exemplo, quero que a saída seja read %A=1, mas não funciona.

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

A maneira mais conveniente de proteger a porcentagem é introduzir outra variável FOR

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

Funciona tão bem colocar o Aem outra variável

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

Atualizar

Uma boa maneira de testar onde o sublinhado está sendo removido é colocar ECHO antes do seu comando. Se o comando original for preservado com o sublinhado, você sabe que o utilitário convert deve ser o culpado.

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

O sublinhado é preservado na minha máquina :-)


Se você tiver mais interesse em como funciona o analisador de comandos, consultehttps://stackoverflow.com/a/4095133/1012053. Essa resposta se preocupa principalmente com a análise de lote, mas as regras são muito semelhantes e uma seção no final descreve brevemente as principais diferenças.

informação relacionada