できない.dev

PowerShell で && が使えない(トークン '&&' は、このバージョンでは有効なステートメント区切りではありません)

&& と || はパイプラインチェーン演算子で PowerShell 7 から追加された。
Windows PowerShell 5.1 では構文エラーになるため、; と if ($?) に置き換えるか pwsh を使う。

公開: 更新:

実行例あり(2026-09-27 に実環境で検証)

要約

npm ci && npm run build のような bash 由来のコマンド列を貼り付けて次のエラーが出るのは、&& がそのバージョンの PowerShell に存在しないからである。

PS C:\work> npm ci && npm run build
トークン '&&' は、このバージョンでは有効なステートメント区切りではありません。
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : InvalidEndOfLine

&& と || はパイプラインチェーン演算子と呼ばれ、公式ドキュメント(新しいタブで開く)にあるとおり PowerShell 7 から実装された。
Windows に標準搭載されている Windows PowerShell 5.1 では構文エラーになる。

7 系(pwsh)に切り替えるのが素直な解決策で、5.1 に留まる必要があるなら ; と if ($?) で同じ意味を書ける。

実行例

Windows に標準で入っている powershell.exe(5.1.26100.9549)で npm ci && npm run build を打つと、npm ci も走らないまま トークン '&&' は、このバージョンでは有効なステートメント区切りではありません。 の ParserError で止まり、npm ci; if ($?) { npm run build } に書き換えると npm run build の built まで通った。
PowerShell 7.4.2 では、同じ npm ci && npm run build の文字列を [ScriptBlock]::Create に渡してもパースエラーにならない。

$ $PSVersionTable.PSVersion
Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      26100  9549
$ npm ci && npm run build
発生場所 行:1 文字:8
+ npm ci && npm run build
+        ~~
トークン '&&' は、このバージョンでは有効なステートメント区切りではありません。
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : InvalidEndOfLine
$ npm ci; if ($?) { npm run build }
up to date in 394ms
 
> demo@1.0.0 build
> node -e "console.log('built')"
 
built
$ $PSVersionTable.PSVersion
Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
7      4      2
$ [ScriptBlock]::Create("npm ci && npm run build") | Out-Null; "パースできた"
パースできた

— 2026-09-27 時点の出力

検証環境

検証日
実行環境
local host (Windows 11 Home, Docker 29.8.0)
バージョン
  • Node.js 22.14.0
  • npm 10.9.2
  • Git 2.48.1.windows.1
  • Docker 29.8.0

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

よくある原因

  1. 実行しているのが 5.1: $PSVersionTable.PSVersion が 5.1.x なら該当する。
    Windows に最初から入っている powershell.exe は 5.1 で、7 系は別途インストールする pwsh.exe である。
    両者は共存する。
  2. bash / cmd のコマンド列をそのまま貼った: && は POSIX シェルの AND-OR リストや cmd.exe の条件付き処理記号に相当する記法で、README の手順をそのまま持ち込むと踏む。
  3. CI が 5.1 を選んでいる: GitHub Actions の Windows ランナーでは shell: powershell が 5.1(PowerShell Desktop)、shell: pwsh が 7 系(PowerShell Core)を指す。
    ただし shell を省略したときの既定は pwsh なので、CI で 5.1 になるのは shell: powershell を明示している場合か、PowerShell Core が入っていないセルフホストランナー(pwsh 指定でも Desktop に落ちる)である。
    手元の pwsh では通るのに CI だけ落ちる場合はこの 2 つを疑う。
  4. パイプと混同している: && はオブジェクトを渡さない。
    左のパイプラインが成功したかどうかだけを見て右を実行する演算子である。

解決策

1. PowerShell 7 で実行する

pwsh -Command "npm ci && npm run build"

バージョンは次で確認する。

$PSVersionTable.PSVersion
Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
7      5      0

2. 5.1 では ; と if ($?) に書き換える

公式ドキュメントが示すとおり、パイプラインチェーン演算子は $? を使った条件分岐と等価である。

npm ci; if ($?) { npm run build }

|| に相当する「失敗したときだけ実行」はこう書く。

npm ci; if (-not $?) { Write-Error "install に失敗した" }

無条件に続けて実行したいだけなら ; だけでよい。&& を「単なる区切り」のつもりで使っていた場合は、; への置換で意図どおりになる。

3. CI ではシェルを明示する

- name: Build
  shell: pwsh
  run: npm ci && npm run build

GitHub ホストの Windows ランナーは shell 省略時も pwsh を使うため、この明示が要るのは shell: powershell を書いている箇所を潰すときと、セルフホストランナーで 7 系の導入を保証したいときである。
ワークフロー全体で揃えるなら defaults.run.shell に指定しておく。

4. 外部コマンドの成否判定に注意する

$? はネイティブコマンドの場合 $LASTEXITCODE を見て決まる。
終了コードを返さないコマンドや、エラーでも 0 を返すコマンドでは分岐が期待どおりに動かない。
その場合は終了コードを直接見る。

npm ci
if ($LASTEXITCODE -eq 0) { npm run build }

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