‘rm’ is not recognized as an internal or external command
Verified on Windows 11, Node 24.20.0 · OpusMill
operable program or batch file.
npm install --save-dev rimraf
- "clean": "rm -rf dist" + "clean": "rimraf dist"
For commands other than rm, shx gives you a
cross-platform version of most of them:
shx cp, shx mkdir -p, shx cat.
Why it happens
npm runs scripts through cmd.exe on Windows, and
cmd.exe has none of the Unix commands. There is no rm, no
cp, no sed. Windows has
del and rmdir, which take different flags and
behave differently, so the answer is not to translate the command
— it is to use something that works everywhere.
| Instead of | Use |
|---|---|
rm -rf dist | rimraf dist |
cp a b | shx cp a b, or copyfiles |
mkdir -p a/b | mkdirp a/b, or shx mkdir -p a/b |
mv a b | shx mv a b |
cat a b > c | a small Node script — redirection differs too |
sed -i ... | a Node script. There is no honest one-liner. |
The part that wastes an afternoon
It may work on your Windows machine and fail in CI, or work in
one terminal and fail in another on the same machine. Git for
Windows ships rm, cp, sed,
grep, ps and more in
C:\Program Files\Git\usr\bin. Git Bash puts that
directory on PATH; the system PATH does not
have it.
So the same command succeeds from Git Bash and fails from cmd, PowerShell, a service, or a CI runner. Checked on this machine:
PS> (Get-Command rm).Source -> nothing (PowerShell aliases rm to Remove-Item)
PS> (Get-Command sed).Source -> C:\Program Files\Git\usr\bin\sed.exe
PS> [Environment]::GetEnvironmentVariable('Path','Machine') -match 'usr.bin'
False
PS> [Environment]::GetEnvironmentVariable('Path','User') -match 'usr.bin'
False
That directory was on PATH only because the shell had been
launched from Git Bash. If a colleague says “it works for
me,” this is usually why — and it is why the fix belongs in
package.json rather than in a PATH setting
nobody else has.
A trap in PowerShell specifically
PowerShell aliases rm to Remove-Item, so
rm -rf build there does not say “not
recognized” at all. It says this:
PS> rm -rf build A parameter cannot be found that matches parameter name 'rf'.
Same cause, different message, and one that sends people looking for a
PowerShell problem rather than a portability one. The alias is why
(Get-Command rm).Source is empty above — there is no
rm.exe being found, just a built-in alias with different
flags.
What about the shell-syntax scripts?
If your script is for FILE in test/*.js; do ...; done, or
uses $(...), or pipes into sed, there is no
package that fixes it. That is a shell program, and cmd.exe cannot run
shell programs. Move it into a .mjs file and call
it with node, which runs anywhere. That is more
work than swapping in rimraf, and it is the only honest
answer.
Check your own project for the rest of this class of bug.
Paste your code or your package.json into
the browser checker — nothing is uploaded,
it runs on your machine — or run
npx github:Hackierz/winbreak over the whole repository.
--fix repairs the npm scripts that have one obvious
answer and refuses the ones that need a human.
Other errors in the same family:
- The fix for 'NODE_ENV' is not recognized
- The fix for spawn EINVAL on Windows
- The fix for ENOENT on node_modules/.bin
- Path too long on Windows
- EPERM on Windows
- Cannot find module, but only in CI
Background: I scanned the 600 most-downloaded
npm CLI packages — 17.4% have a package.json
script that cannot run on Windows.