บรรทัดคำสั่งของ Windows ImageMagick เปอร์เซนต์หนีออกมา


2

ฉันพยายามใช้ ImageMagick จากบรรทัดคำสั่งใน Windows 7 เพื่อแปลงภาพหลายภาพในครั้งเดียว ฉันต้องการใช้อินเทอร์เฟซตัวเลือก - ชุด แต่ฉันได้รับผลลัพธ์ที่ไม่คาดคิด ตัวอย่างสั้น ๆ ของความแปลกประหลาดบางอย่างที่ฉันเห็นคือ:

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

เกิดอะไรขึ้นที่นี่? ทำไมการแทรกเครื่องหมายรูปหมวกจะทำให้ขีดเส้นใต้ถูกเก็บรักษาไว้? เครื่องหมายรูปหมวก (^) แม้แต่ escaper ที่ถูกต้องที่จะลองหรือไม่? พฤติกรรมนี้เกิดจากการขยายตัวของตัวแปรสภาพแวดล้อมของเชลล์คำสั่งหรือความแปลกประหลาดเป็นผลมาจากวิธีที่ ImageMagick จัดการกับค่าเปอร์เซ็นต์ ไม่ว่าจะด้วยวิธีใดมีหลักการทั่วไปเกี่ยวกับการใช้สัญลักษณ์ร้อยละในบรรทัดคำสั่งที่สามารถติดตามเพื่อทำให้เกิดพฤติกรรมที่คาดการณ์ได้หรือไม่

สิ่งที่ฉันต้องการทำจริง ๆ คือเวอร์ชันของคำสั่งด้านบนที่มีชุดคุณสมบัติมากมายอีกมากมายที่สามารถจัดการชื่อไฟล์ที่มีอักขระพิเศษเช่นช่องว่างและสัญลักษณ์เปอร์เซ็นต์ได้ แต่ดูเหมือนโง่มากที่จะลองว่า . ในที่สุดฉันจะต้องดำเนินการคำสั่งจากโปรแกรม. NET

ฉันดูที่http://www.robvanderwoude.com/escapechars.phpและEscaping% ในชื่อไฟล์ / ชื่อโฟลเดอร์ที่บรรทัดคำสั่งแต่ไม่สามารถหาวิธีใช้คำแนะนำกับปัญหาของฉันได้

ปรับปรุง

การเพิ่มตัวอย่างเพิ่มเติมเพื่อตอบคำถามในความคิดเห็นจาก @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โดยไม่คำนึงว่าวาง carets ไว้ภายใน:

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

จะเกิดอะไรขึ้นถ้าคุณใส่เครื่องหมายรูปหมวกหน้าเครื่องหมายขีดล่างแทน?
dbenham

ดังนั้นคุณได้ลองหนีคำพูดโดยรอบนอกเหนือไปจากร้อยละ? ^"^%[filename:foo]_^%[filename:bar].png^"
Synetech

คำตอบ:


3

ฉันไม่สามารถอธิบายพฤติกรรมแปลก ๆ ที่คุณเห็นได้ มันเกือบจะดูเหมือนว่าเป็นผลมาจากการประมวลผลร้อยละ 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%"

สถานการณ์มีความซับซ้อนขึ้นเล็กน้อยเมื่อมีลำไส้ใหญ่ เครื่องหมายจุดคู่จะถูกใช้โดยการขยายตัวแปรสำหรับการทดแทนและการดำเนินงาน substring ชื่อตัวแปรคือข้อความระหว่างเปอร์เซ็นต์แรกและเครื่องหมายโคลอน

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 ในตัวอย่างนี้ฉันต้องการให้เอาท์พุทอ่าน%A=1แต่มันไม่ทำงาน

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

วิธีที่สะดวกที่สุดในการปกป้องเปอร์เซ็นต์คือการแนะนำตัวแปรอีกตัวหนึ่ง

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 คำตอบนั้นส่วนใหญ่เกี่ยวข้องกับการแยกแบทช์ แต่กฎคล้ายกันมากและส่วนท้ายอธิบายความแตกต่างที่สำคัญอย่างย่อ ๆ


ขอบคุณสำหรับคำอธิบายและตัวอย่าง ฉันพอใจเป็นอย่างยิ่งที่ convert.exe ของ ImageMagick เป็นสาเหตุของพฤติกรรมที่ไม่คาดคิด
user4851
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.