Skip to content
shellmap

move-itemPowerShell's move/rename cmdlet — the mv equivalent across all 5 shells

Equivalents in every shell

Bashunix
mv source dest

POSIX `mv` renames within a filesystem (atomic) and copies+deletes across filesystems. `-i` prompts on overwrite, `-n` skips existing, `-v` prints each rename. No built-in undo. Trailing `/` on `dest` enforces "must be a directory" semantics.

Zshunix
mv source dest

Same `/bin/mv`. zsh adds `zmv` (autoload via `autoload -U zmv`) — pattern-based bulk rename: `zmv '(*).log' '$1.txt'`. zmv is dry-run with `-n`; this is the killer feature for batch renames.

Fishunix
mv source dest

Same external `mv`. Fish has no built-in batch rename; the idiom is `for f in *.log; mv $f (string replace .log .txt $f); end`.

PowerShellwindows
Move-Item -Path source -Destination dest

PowerShell-native cmdlet (aliases `mv`, `move`, `mi`). Works across PS providers — file system, registry, certificate store. `-Force` overwrites read-only destinations; `-Confirm` prompts; `-WhatIf` dry-runs. Wildcards on `-Path`, single literal on `-Destination`.

cmd.exewindows
move source dest

Built-in `move`. Renames within a drive (atomic) and copies+deletes across drives. `/Y` suppresses overwrite prompt; `/-Y` forces the prompt. `ren oldname newname` is the rename-only variant — same drive, no path change. Wildcards work on the source but the destination must be a single name pattern.

Worked examples

Rename a single file

Bash
mv old.txt new.txt
Zsh
mv old.txt new.txt
PowerShell
Move-Item old.txt new.txt
cmd.exe
ren old.txt new.txt

Move all .log files to a backup folder, overwriting existing

Bash
mv -f *.log backup/
PowerShell
Move-Item -Path *.log -Destination backup\ -Force
cmd.exe
move /Y *.log backup\

Dry-run a bulk move (preview without executing)

Zsh
zmv -n '(*).log' '$1.bak'
PowerShell
Move-Item -Path *.log -Destination *.bak -WhatIf

Gotchas

  • `Move-Item -Destination` does NOT accept a directory path with a trailing `\` to mean 'into here' the way Unix `mv source dir/` does. If `dest` exists as a directory, `Move-Item source dest` moves into it; if `dest` does not exist, it RENAMES `source` to `dest`. The trailing-slash trick that prevents accidental rename in mv (`mv file dir/`) has no equivalent — explicit `Test-Path dest -PathType Container` is the safe form.
  • Cross-volume moves are not atomic on either side: `mv` and `Move-Item` both fall back to copy+delete when source/dest live on different filesystems / drives. A power loss mid-move can leave the source intact and the dest partial; treat cross-volume moves as conceptually `cp + rm`. For atomic on Linux, `rename(2)` is same-fs only.
  • `Move-Item` cannot move a file to a different PROVIDER (e.g. file system → registry). The error is `Source and destination paths must be of the same provider type` — surprising the first time. To bridge providers, `Get-Item source | ForEach-Object { Set-Item -Path dest -Value $_.Value }` is the manual pattern.
  • PowerShell wildcards in `-Path` follow PowerShell glob semantics, NOT regex. `Move-Item *.log archive\` works; `Move-Item ^.*\.log$ archive\` does NOT (regex is not supported on Path). For regex selection, pipe: `Get-ChildItem | Where-Object Name -Match '^app.*\.log$' | Move-Item -Destination archive\`.
  • cmd `move *.log subdir\` succeeds if `subdir` exists, but if `subdir` does NOT exist, `move *.log subdir` (no trailing `\`) RENAMES the first match to `subdir` and ERRORS on the rest. Always end the destination with `\` when you mean a directory; this is the most common cmd `move` gotcha.

WSL & PowerShell Core notes

pwsh`Move-Item` works on Linux/macOS pwsh against the file system provider — same syntax as Windows. The aliases `mv`, `move`, `mi` are removed from Linux/macOS pwsh so the system `/bin/mv` resolves first; spell `Move-Item` in cross-platform scripts to be unambiguous.
WSLMove-Item across the WSL boundary works (`Move-Item C:\file.txt \\wsl$\Ubuntu\home\me\file.txt`) but is SLOW — DrvFs / 9P has high per-operation overhead. For bulk moves between Windows and WSL, prefer `cp -a` from inside WSL (5-10× faster than going through `\\wsl$\` on the Windows side).

Related commands