できない.dev

PowerShell で curl のオプションが効かない(Invoke-WebRequest の別名)

Windows PowerShell 5.1 では curl は Invoke-WebRequest の別名で、-I や -o といった本家のオプションを解釈しない。
curl.exe と拡張子まで書いて呼ぶか、cmdlet 側のパラメータに読み替える。

公開:

要約

Windows PowerShell 5.1 の curl は本家の curl ではない。Invoke-WebRequest のリファレンス(新しいタブで開く) が「Windows PowerShell includes the following aliases」として iwr / curl / wget を挙げているとおり、cmdlet への別名である。

PS> curl -I https://example.com
Invoke-WebRequest : Cannot process command because of one or more missing mandatory parameters: Uri.

-I はヘッダのみ取得する curl のオプションだが、PowerShell はこれをパラメータ名の前方一致として扱い -InFile に結び付ける。
続く URL はそのファイル名として吸われるため、位置引数の -Uri が埋まらず、URL を渡したはずなのに「Uri が無い」と言われる。

よくある原因

  1. 別名の優先度: PowerShell は同名の別名と実行ファイルがあれば別名を先に選ぶ。
    Windows 10 以降には C:\Windows\System32\curl.exe が同梱されているが、curl と打つ限りそちらは呼ばれない。
  2. 前方一致でパラメータに化ける: PowerShell はパラメータ名の省略を前方一致で解決する。-I-InFile に一致してしまうので、存在しないオプションを渡したときのような「そんなパラメータは無い」というエラーにはならない。-Q のようにどれにも一致しない場合だけ別のメッセージが出る。
    原因の切り分けが遅れやすい。
  3. 手順書の使い回し: Linux / macOS 向けの curl -sSL ... | sh のような 1 行を、そのまま PowerShell の窓へ貼っている。
  4. バージョン差: PowerShell 7 系にこの別名は無く、curl は素直に curl.exe へ解決される。
    7 で検証した手順が 5.1 で落ちる。
  5. 解析の既定が変わった: 2025 年 12 月のセキュリティ更新(CVE-2025-54100)以降、5.1 の Invoke-WebRequest-UseBasicParsing を付けないと確認プロンプトを出す。
    スクリプトの中では応答できず、そこで止まる。

解決策

1. curl.exe と書く

curl.exe -I https://example.com
curl.exe -sSL -o out.zip https://example.com/file.zip

拡張子まで書けば別名は当たらず、本家の curl がそのまま動く。
手順書を移植するときはこれが最短である。

2. いま何に解決されているか確かめる

Get-Command curl | Format-List Name, CommandType, Definition
Name        : curl
CommandType : Alias
Definition  : Invoke-WebRequest

CommandTypeAlias なら別名、Application なら実行ファイルである。
5.1 と 7 のどちらで動かしているかを推測せずに済む。

3. cmdlet のパラメータへ読み替える

Invoke-WebRequest -Uri https://example.com -Method Head -UseBasicParsing
Invoke-WebRequest -Uri https://example.com/file.zip -OutFile out.zip -UseBasicParsing

-I-Method Head-o-OutFile に対応する。
5.1 では -UseBasicParsing も付けて、確認プロンプトを避ける。

4. 別名を外す

Remove-Item Alias:curl

そのセッションでだけ別名が消え、curlcurl.exe へ解決されるようになる。Remove-Alias は PowerShell 6.0 で追加された cmdlet なので、5.1 では上の書き方を使う。

5. スクリプトでは名前を固定する

共有するスクリプトに curl とだけ書くと、実行者のバージョンで意味が変わる。curl.exeInvoke-WebRequest のどちらかに寄せておけば、この曖昧さは残らない。

この記事は役立ちましたか?