Windows 명령줄 ImageMagick 백분율 이스케이프

Windows 명령줄 ImageMagick 백분율 이스케이프

Windows 7의 명령줄에서 ImageMagick을 사용하여 한 번에 많은 이미지를 변환하려고 합니다. -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를 넣는 것입니다. 원래 명령이 밑줄과 함께 보존되면 변환 유틸리티가 범인임이 틀림없다는 것을 알 수 있습니다.

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. 그 대답은 주로 배치 구문 분석과 관련이 있지만 규칙은 매우 유사하며 마지막 섹션에서는 주요 차이점을 간략하게 설명합니다.

관련 정보