Prozent-Escapes für die Windows-Befehlszeile von ImageMagick

Prozent-Escapes für die Windows-Befehlszeile von ImageMagick

Ich versuche, ImageMagick über die Befehlszeile in Windows 7 zu verwenden, um mehrere Bilder gleichzeitig zu konvertieren. Ich würde gerne die Option -set verwenden, erhalte aber unerwartete Ergebnisse. Ein kurzes Beispiel für einige der Merkwürdigkeiten, die mir auffallen, ist Folgendes:

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

Beachten Sie, dass der Unterstrich auf mysteriöse Weise aus dem Ausgabedateinamen gelöscht wird. Ich kann ein Zirkumflex (^) verwenden, um das zweite Prozentzeichen zu maskieren und den Unterstrich beizubehalten:

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

Was ist hier los? Warum bleibt der Unterstrich beim Einfügen des Zirkumflexes erhalten? Ist das Zirkumflex (^) überhaupt der richtige Escaper? Liegt dieses Verhalten an der Erweiterung der Umgebungsvariablen der Befehlsshell oder ist die Merkwürdigkeit auf die Art und Weise zurückzuführen, wie ImageMagick die Prozent-Escapes verarbeitet? Gibt es in jedem Fall allgemeine Grundsätze für die Verwendung von Prozentsymbolen in Befehlszeilenargumenten, die befolgt werden können, um ein vorhersehbares Verhalten zu erzielen?

Eigentlich möchte ich eine Version des obigen Befehls mit viel mehr festgelegten Eigenschaften erstellen, die mit vielen Dateinamen mit Sonderzeichen wie Leerzeichen und Prozentzeichen umgehen kann, aber es scheint mir töricht, das zu versuchen, wenn ich dieses viel einfachere Beispiel nicht verstehe. Letztendlich muss ich den Befehl aus einem .NET-Programm ausführen.

Ich habe mir angesehenhttp://www.robvanderwoude.com/escapechars.phpUndEscapen von %'s in Datei-/Ordnernamen in der Kommandozeilekonnte aber nicht herausfinden, wie ich den Rat auf mein Problem anwenden sollte.

Aktualisieren

Ich füge einige weitere Beispiele hinzu, um Fragen in Kommentaren von @dbenham und @Synetech zu beantworten.

Wenn man den Unterstrich wie im letzten Beispiel oben vor das zweite Prozentzeichen verschiebt, entsteht eine Datei mit dem Namen 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

Das Escapen der umgebenden Anführungszeichen mithilfe eines Caretzeichens führt immer zu einem helloworld.png, unabhängig von der Position des Caretzeichens darin:

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

Antwort1

Ich kann das seltsame Verhalten, das Sie beobachten, nicht ganz erklären. Es scheint fast so, als sei es ein Ergebnis der Prozentverarbeitung von cmd.exe, aber es entspricht nicht ganz dem Verhalten von cmd.exe, so wie ich es verstehe.

Das Escapen von Prozenten in einer Batchdatei ist einfach – verdoppeln Sie sie einfach. Aber das funktioniert nicht über die Kommandozeile. Technisch gesehen gibt es keine Möglichkeit, einem Prozent in der Windows-Befehlszeile cmd.exe zu entkommen.

Die Befehlszeile kann Prozente auf zwei Arten erweitern:

1) Erweitern Sie Umgebungsvariablen.

Wenn der Text zwischen zwei Prozenten mit dem Namen einer Umgebungsvariablen übereinstimmt, wird die Prozentkonstruktion durch den Wert ersetzt.

C:\test>set test=hello

C:\test>echo %test%
hello

Wenn der Text zwischen den Prozentzeichen nicht mit dem Namen einer Umgebungsvariable übereinstimmt, bleibt der vollständige Originaltext erhalten.

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

In der Dokumentation von Microsoft selbst heißt es, dass Sie dem Prozentzeichen entgehen können, indem Sie davor ein Zirkumflex setzen.

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

Aber das ist kein wirkliches Escapen des Prozentzeichens. Stattdessen wird nach einer Variable namens gesucht test^und diese nicht gefunden. Der Originaltext bleibt also intakt. Dann werden die Zirkumflexe während der normalen Escape-Verarbeitung entfernt. Dies kann nachgewiesen werden, indem eine Variable mit dem Zirkumflex im Namen definiert wird.

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

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

Das Zirkumflex vor dem ersten Prozentzeichen hat keine Wirkung. Sie können ein Zirkumflex an beliebiger Stelle zwischen den Prozentzeichen platzieren und es verhindert die Erweiterung der Variable, solange keine Variable mit dem Zirkumflex im Namen existiert.

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

Wenn der Text in Anführungszeichen steht, wird das Caretzeichen nicht gelöscht, es sei denn, die Anführungszeichen werden ebenfalls maskiert.

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

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

Bei Doppelpunkten ist die Situation etwas komplizierter. Der Doppelpunkt wird von der Variablenerweiterung für Substitutions- und Teilzeichenfolgenoperationen verwendet. Der Variablenname ist der Text zwischen dem ersten Prozentzeichen und dem Doppelpunkt.

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

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

Wenn der Text zwischen dem ersten Prozentzeichen und dem Doppelpunkt nicht mit einem Variablennamen übereinstimmt oder wenn der Text zwischen dem Doppelpunkt und dem letzten Prozentzeichen keine gültige Ersetzung oder Teilzeichenfolgenkonstruktion ist, bleibt der Originaltext ohne Ersetzung erhalten.

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

Dieses letzte Beispiel ähnelt Ihrer Situation am meisten. Der Text zwischen Ihrem ersten Prozent und dem Doppelpunkt entspricht keiner Variable, und der Text zwischen dem Doppelpunkt und dem letzten Prozent ist keine Substitution oder Teilzeichenfolgenkonstruktion.so dass das Gesamtkonstrukt erhalten bleiben sollte,einschließlich des Unterstrichs. Aus diesem Grund sehe ich nicht, wie cmd.exe Ihren Unterstrich entfernen könnte.Aber die Tatsache, dass das Hinzufügen eines Zirkumflexes vor dem zweiten Prozentzeichen den Unterstrich beibehält, macht mich misstrauisch. Ich würde wirklich gerne wissen, was passiert, wenn Sie das Zirkumflex stattdessen vor den Unterstrich setzen.


2) Erweitern Sie FOR-Variablen

In Ihrem Fall kein Problem, aber Prozente können auch Probleme verursachen, wenn eine FOR-Schleife aktiv ist. In diesem Fall gibt es keine Möglichkeit, den Prozentwert durch Verwendung eines Zirkumflexes zu schützen, da der Zirkumflex vor der FOR-Variablenerweiterung entfernt wird. In diesem Beispiel möchte ich, dass die Ausgabe lautet %A=1, aber es funktioniert nicht.

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

Der bequemste Weg, den Prozentsatz zu schützen, besteht darin, eine weitere FOR-Variable einzuführen

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

Es funktioniert genauso gut, das Ain eine andere Variable einzufügen

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

Aktualisieren

Eine gute Möglichkeit, zu testen, wo der Unterstrich entfernt wird, besteht darin, ECHO vor Ihren Befehl zu setzen. Wenn der ursprüngliche Befehl mit dem Unterstrich erhalten bleibt, wissen Sie, dass das Konvertierungsprogramm der Übeltäter sein muss.

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

Der Unterstrich bleibt auf meinem Rechner erhalten :-)


Wenn Sie mehr über die Funktionsweise des Befehlsparsers erfahren möchten, lesen Siehttps://stackoverflow.com/a/4095133/1012053. Diese Antwort beschäftigt sich hauptsächlich mit der Batch-Analyse, aber die Regeln sind sehr ähnlich und in einem Abschnitt am Ende werden die wichtigsten Unterschiede kurz beschrieben.

verwandte Informationen