Skip to content
MagickCmd报错 › 同一条命令在 bash 里正常,在 PowerShell 或 cmd 里失败

同一条命令在 bash 里正常,在 PowerShell 或 cmd 里失败

^ > < ! 和 % 这些几何字符同时也是 shell 元字符。PowerShell、cmd.exe 以及 .bat 文件里各自该怎么加引号。

你抄了一条在别人 Mac 上跑得好好的命令,在 Windows 上却什么都没发生、多出一个奇怪的文件、或者直接报错。

原因

ImageMagick 的几何后缀和 shell 语法撞车了:

字符ImageMagick 里的含义shell 里的含义
>仅当更大时缩小把输出重定向到文件
<仅当更小时放大从文件读取输入
^填满目标框、允许溢出cmd.exe 的转义符
!强制精确尺寸交互式 bash 的历史展开
%百分比,以及文件名计数器cmd / bat 里的变量展开

shell 会在 ImageMagick 看到它们之前就先处理掉。

实际会发生什么

magick in.jpg -resize 800x600> out.jpg

bash 把这条理解成「运行 magick in.jpg -resize 800x600,并把它的输出重定向到一个叫 out.jpg 的文件」。你会得到一张被无条件缩放的图,外加一个多余的空文件。不报错,但结果是错的 —— 这是最坑的一类失败。

各个 shell 的正确写法

# bash / zsh / sh
magick in.jpg -resize '800x600>' out.jpg

# PowerShell
magick in.jpg -resize '800x600>' out.jpg

# cmd.exe
magick in.jpg -resize "800x600>" out.jpg

bash 和 PowerShell 里单引号最保险,因为它会屏蔽所有解释。cmd.exe 根本不认识单引号,必须用双引号。

.bat 文件里的百分号问题

在 cmd.exe 里,加引号保护不了 %。写在 .bat.cmd 文件里时,每个字面上的百分号都要写两遍:

REM 直接在命令行敲
magick in.jpg -crop 400x400 +repage tile_%02d.jpg

REM 写在 .bat 文件里
magick in.jpg -crop 400x400 +repage tile_%%02d.jpg

循环变量同理 —— 命令行里的 %f 在文件里要写成 %%fidentify -format 的格式字符串也一样。

括号

ImageMagick 的子表达式括号同样是 shell 敏感字符。老教程里为 bash 写的是转义:

magick in.jpg \( logo.png -resize 20% \) -composite out.jpg

这个反斜杠转义在 PowerShell 和 cmd 里都不管用。加引号则三种 shell 通用:

magick in.jpg '(' logo.png -resize 20% ')' -composite out.jpg

这就是本站的生成器采用这种写法的原因 —— 一种形式在三个 shell 里都正确。

PowerShell 的一些细节

  • PowerShell 的参数拆分方式和 cmd 不同。如果一个参数里既有空格又有元字符,整个用单引号包起来。
  • 双引号字符串里 $ 会被当成变量。任何含 $ 的 ImageMagick 格式字符串请用单引号。
  • PowerShell 7 处理原生命令参数比 5.1 更可预测。如果一条命令在 7 上能跑、5.1 上不能,通常就是引号的差别。
  • --% 可以让 PowerShell 完全停止解析:magick --% in.jpg -resize 800x600^ out.jpg。比较粗暴,但整条粘贴长命令时很有用。

批量循环

# bash
mkdir -p out
for f in *.jpg; do magick "$f" -resize '1600>' "out/$f"; done

# PowerShell
New-Item -ItemType Directory -Force out | Out-Null
Get-ChildItem *.jpg | ForEach-Object { magick $_.FullName -resize '1600>' "out/$($_.Name)" }

# cmd.exe(命令行里这样写;.bat 文件里 % 要写两遍)
if not exist out mkdir out
for %f in (*.jpg) do magick "%f" -resize "1600>" "out\%~nxf"

本站页面顶部有 shell 选择器 —— 切换它,所有命令会自动按对应规则重新加引号。


相关页面

Copied