2 votes

Ligne de commande Windows ImageMagick percent escapes

J'essaie d'utiliser ImageMagick à partir de la ligne de commande sous Windows 7 pour convertir plusieurs images à la fois. J'aimerais utiliser l'interface de l'option -set, mais j'obtiens des résultats inattendus. Voici un petit exemple des bizarreries que j'observe :

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

Remarquez que le caractère de soulignement est mystérieusement supprimé du nom du fichier de sortie. Je peux utiliser un caret (^) pour échapper au deuxième signe de pourcentage afin de conserver le trait de soulignement :

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

Que se passe-t-il ici ? Pourquoi l'insertion de la virgule entraîne-t-elle la conservation du trait de soulignement ? Le caret (^) est-il même l'escaper correct à essayer ? Ce comportement est-il dû à l'expansion de la variable d'environnement Shell ou l'étrangeté résulte-t-elle de la façon dont ImageMagick gère les échappements en pourcentage ? Quoi qu'il en soit, existe-t-il des principes généraux concernant l'utilisation des symboles de pourcentage dans les lignes de commande qui peuvent être suivis pour obtenir un comportement prévisible ?

En fait, je voudrais faire une version de la commande ci-dessus avec beaucoup plus de propriétés définies, qui puisse gérer des noms de fichiers avec des caractères spéciaux tels que des espaces et des symboles de pourcentage, mais il semble idiot d'essayer cela si je ne peux pas comprendre cet exemple beaucoup plus simple. En fin de compte, j'aurai besoin d'exécuter la commande à partir d'un programme .NET.

J'ai examiné http://www.robvanderwoude.com/escapechars.php y Échapper aux % dans les noms de fichiers/dossiers à la ligne de commande mais je n'arrivais pas à comprendre comment appliquer les conseils à mon problème.

アップデート

Ajout de quelques exemples supplémentaires pour répondre aux questions posées dans les commentaires de @dbenham et @Synetech.

En déplaçant le trait de soulignement d'avant le deuxième symbole de pourcentage, comme dans le dernier exemple ci-dessus, à avant le trait de soulignement, on obtient un fichier nommé 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

Le fait de ne pas mettre les guillemets entre parenthèses aboutit toujours au résultat suivant helloworld.png indépendamment de l'endroit où les carets sont placés à l'intérieur :

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

3voto

dbenham Points 10555

Je ne peux pas vraiment expliquer le comportement étrange que vous observez. Il semble presque que ce soit le résultat du traitement de cmd.exe percent, mais cela ne correspond pas tout à fait au comportement de cmd.exe tel que je le comprends.

Il est facile d'échapper aux pourcentages dans un fichier batch : il suffit de les doubler. Mais cela ne fonctionne pas à partir de la ligne de commande. Techniquement, il n'existe aucun moyen d'échapper à un pourcentage sur la ligne de commande Windows cmd.exe.

La ligne de commande peut développer les pourcentages de deux manières :

1) Développez les variables d'environnement.

Si le texte entre deux pourcentages correspond au nom d'une variable d'environnement, la construction en pourcentage est remplacée par la valeur.

C:\test>set test=hello

C:\test>echo %test%
hello

Si le texte entre les pourcentages ne correspond pas à un nom de variable d'environnement, le texte original complet est conservé.

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

La documentation de Microsoft indique qu'il est possible d'échapper au pourcentage en plaçant un caret devant.

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

Mais ce n'est pas vraiment échapper au pour cent. Au lieu de cela, il recherche une variable nommée test^ et ne le trouve pas. Le texte original n'est donc pas perturbé. Les carets sont ensuite supprimés lors du traitement normal de l'échappement. Cela peut être prouvé en définissant une variable avec le caret dans le nom.

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

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

Le caret avant le premier pour cent ne fait rien. Vous pouvez placer un caret n'importe où entre les pourcentages et il empêchera l'expansion de la variable tant qu'aucune variable n'existe avec le caret dans le nom.

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

Si le texte est entre guillemets, le caret ne sera pas supprimé à moins que les guillemets ne soient également échappés.

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

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

La situation est un peu plus compliquée lorsqu'il y a des deux points. Les deux points sont utilisés par l'expansion des variables pour les opérations de substitution et de sous-chaîne. Le nom de la variable est le texte compris entre le premier pour cent et les deux points.

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

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

Si le texte entre le premier pour cent et les deux points ne correspond pas à un nom de variable, ou si le texte entre les deux points et le dernier pour cent n'est pas une substitution valide ou une construction de sous-chaîne, le texte original est préservé sans substitution.

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

Ce dernier exemple ressemble le plus à votre situation. Le texte entre le premier pour cent et les deux points ne correspond pas à une variable, et le texte entre les deux points et le dernier pour cent n'est pas une construction de substitution ou de sous-chaîne, Il convient donc de préserver l'ensemble de la construction, y compris le trait de soulignement . Pour cette raison, je ne vois pas comment cmd.exe pourrait supprimer votre trait de soulignement. Mais le fait que l'ajout d'un caret avant le deuxième pour cent préserve le trait de soulignement me rend méfiant. J'aimerais vraiment savoir ce qui se passe si l'on place le point d'interrogation avant le trait de soulignement.

2) Étendre les variables FOR

Ce n'est pas un problème dans votre cas, mais les pourcentages peuvent aussi causer des problèmes si un boucle for est en vigueur. Il n'y a aucun moyen de protéger le pourcentage en utilisant un caret dans ce cas, parce que le caret est supprimé avant l'expansion de la variable FOR. Dans cet exemple, je veux que le résultat soit le suivant %A=1 mais cela ne fonctionne pas.

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

La façon la plus pratique de protéger le pourcentage est d'introduire une autre variable FOR

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

Il est tout aussi efficace de mettre le A dans une autre variable

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

アップデート

Un bon moyen de tester où le trait de soulignement est supprimé est de placer ECHO avant votre commande. Si la commande originale est conservée avec le trait de soulignement, alors vous savez que l'utilitaire de conversion doit être le coupable.

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

Le trait de soulignement est conservé sur ma machine :-)


Si vous souhaitez en savoir plus sur le fonctionnement de l'analyseur de commandes, consultez le site suivant https://stackoverflow.com/a/4095133/1012053 . Cette réponse concerne principalement l'analyse par lots, mais les règles sont très similaires, et une section à la fin décrit brièvement les principales différences.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X