CMD vs PowerShell vs Bash — comandos equivalentes
A mesma tarefa no Prompt de Comando, no PowerShell e no bash, lado a lado: arquivos, grep, variáveis de ambiente, processos, rede, serviços e scripts.
Última verificação: 2026-10-18, conferido com a referência do PowerShell 7.6 e do Windows PowerShell 5.1 no Microsoft Learn, a referência de Comandos do Windows e o manual do GNU Bash 5.2.
Arquivos e pastas
| Tarefa | CMD (Prompt de Comando) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Listar arquivos # Aliases do PowerShell: gci, dir e, no Windows, ls. | dir | Get-ChildItem | ls -l |
| Listar todos os arquivos recursivamente # | dir /s /b | Get-ChildItem -Recurse -File | find . -type f |
| Mostrar o diretório atual # No CMD, cd sem argumento mostra o diretório atual. Alias do PowerShell: pwd, gl; também há a variável $PWD. | cd | Get-Location | pwd |
| Mudar de diretório # O CMD precisa de /d para mudar de unidade além de pasta. Aliases do PowerShell: cd, sl, chdir. | cd /d D:\work | Set-Location D:\work | cd /home/me/work |
| Ir para o diretório pessoal # | cd %USERPROFILE% | Set-Location ~ | cd ~ |
| Criar uma pasta (com as pastas-pai) # O mkdir do CMD cria as pastas intermediárias quando as extensões de comando estão ativadas (o padrão). No PowerShell, mkdir é uma função que encapsula New-Item -ItemType Directory. | mkdir a\b\c | New-Item -ItemType Directory -Path a\b\c | mkdir -p a/b/c |
| Criar um arquivo vazio # | type nul > file.txt | New-Item file.txt | touch file.txt |
| Copiar um arquivo # | copy src.txt dst.txt | Copy-Item src.txt dst.txt | cp src.txt dst.txt |
| Copiar uma pasta recursivamente # xcopy src dst /E /I também funciona; o robocopy é a ferramenta com suporte e pode retomar e tentar de novo. | robocopy src dst /E | Copy-Item src dst -Recurse | cp -r src dst |
| Espelhar uma pasta exatamente Perigoso # Perigo: Os dois apagam do destino os arquivos que não estão na origem. Inverter os dois caminhos apaga a pasta que você queria manter. robocopy /L e rsync -n fazem uma simulação. | robocopy src dst /MIR | (no cmdlet; call robocopy) | rsync -a --delete src/ dst/ |
| Mover um arquivo # | move a.txt archive\ | Move-Item a.txt archive\ | mv a.txt archive/ |
| Renomear um arquivo # | ren old.txt new.txt | Rename-Item old.txt new.txt | mv old.txt new.txt |
| Excluir um arquivo # | del file.txt | Remove-Item file.txt | rm file.txt |
| Excluir uma pasta e o conteúdo dela Perigoso # Perigo: Sem Lixeira e sem confirmação com /q, -Force ou -f. Confira o caminho antes; no PowerShell, adicione -WhatIf para ver o que seria removido. | rmdir /s /q folder | Remove-Item folder -Recurse -Force | rm -rf folder |
| Criar um link simbólico # No Windows, criar links simbólicos exige um prompt elevado, a menos que o Modo de Desenvolvedor esteja ativado. Atenção à ordem dos argumentos: primeiro o link no CMD/PowerShell, primeiro o destino no ln. | mklink link.txt target.txt
mklink /D linkdir targetdir | New-Item -ItemType SymbolicLink -Path link.txt -Target target.txt | ln -s target.txt link.txt |
| Alterar permissões de arquivo # O Windows usa ACLs, não bits rwx; o icacls costuma ser mais fácil que o Set-Acl. | icacls file.txt /grant alice:F | Get-Acl / Set-Acl | chmod 644 file.txt |
| Checksum de arquivo (SHA-256) # Get-FileHash usa SHA256 por padrão; -Algorithm MD5 ou SHA1 para os outros. macOS: shasum -a 256. | certutil -hashfile file.iso SHA256 | Get-FileHash file.iso | sha256sum file.iso |
| Criar um arquivo zip # O tar.exe (bsdtar) vem com o Windows 10 1803 ou posterior; -a escolhe o formato pela extensão .zip. | tar -a -c -f out.zip folder | Compress-Archive -Path folder -DestinationPath out.zip | zip -r out.zip folder |
| Extrair um arquivo zip # | tar -xf out.zip | Expand-Archive out.zip -DestinationPath dest | unzip out.zip -d dest |
Ler e gravar o conteúdo de arquivos
| Tarefa | CMD (Prompt de Comando) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Mostrar um arquivo # Aliases do PowerShell: gc, type e, no Windows, cat. | type file.txt | Get-Content file.txt | cat file.txt |
| Ver um arquivo página por página # | more file.txt | Get-Content file.txt | Out-Host -Paging | less file.txt |
| Primeiras 10 linhas # -Head é um alias de -TotalCount. | Sem comando nativo | Get-Content file.txt -TotalCount 10 | head -n 10 file.txt |
| Últimas 10 linhas # | Sem comando nativo | Get-Content file.txt -Tail 10 | tail -n 10 file.txt |
| Acompanhar um arquivo de log # | Sem comando nativo | Get-Content app.log -Tail 10 -Wait | tail -f app.log |
| Gravar texto em um arquivo (sobrescrever) # No CMD, um espaço antes do > vai parar no arquivo. No Windows PowerShell 5.1, > grava em UTF-16 LE; o PowerShell 7 grava UTF-8 sem BOM. Set-Content -Encoding utf8 é explícito nos dois. | echo hello> file.txt | 'hello' | Set-Content file.txt | echo hello > file.txt |
| Acrescentar texto a um arquivo # | echo hello>> file.txt | Add-Content file.txt 'hello' | echo hello >> file.txt |
| Contar linhas # | find /c /v "" file.txt | (Get-Content file.txt).Count | wc -l file.txt |
| Comparar dois arquivos # No PowerShell no Windows, diff é um alias de Compare-Object, não um diff de texto. | fc a.txt b.txt | Compare-Object (Get-Content a.txt) (Get-Content b.txt) | diff a.txt b.txt |
| Ordenar linhas # | sort file.txt | Get-Content file.txt | Sort-Object | sort file.txt |
| Linhas únicas # | Sem comando nativo | Get-Content file.txt | Sort-Object -Unique | sort -u file.txt |
| Substituir texto em um arquivo # -replace usa expressões regulares; os parênteses leem o arquivo inteiro antes de o Set-Content reabri-lo. O sed do macOS precisa de -i ''. | Sem comando nativo | (Get-Content f.txt) -replace 'old','new' | Set-Content f.txt | sed -i 's/old/new/g' f.txt |
Pesquisa (equivalentes do grep)
| Tarefa | CMD (Prompt de Comando) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Encontrar texto em arquivos # Select-String não diferencia maiúsculas e minúsculas por padrão (-CaseSensitive para mudar). Para subpastas: Get-ChildItem -Recurse -Filter *.log | Select-String error. | findstr /s /i /n "error" *.log | Select-String -Path *.log -Pattern error | grep -rin 'error' --include='*.log' . |
| Filtrar a saída de um comando # | ipconfig | findstr IPv4 | ipconfig | Select-String IPv4 | ip a | grep inet |
| Linhas que NÃO correspondem # | findstr /v "DEBUG" app.log | Select-String -Path app.log -Pattern DEBUG -NotMatch | grep -v DEBUG app.log |
| Pesquisar com regex # O findstr aceita só um pequeno subconjunto de regex (sem |, sem {n}). O Select-String usa expressões regulares do .NET. | findstr /r "^ERR.*timeout" app.log | Select-String -Path app.log -Pattern '^ERR.*timeout' | grep -E '^ERR.*timeout' app.log |
| Encontrar arquivos pelo nome # | dir /s /b *.log | Get-ChildItem -Recurse -Filter *.log | find . -name '*.log' |
| Descobrir onde está um programa # No PowerShell, where é um alias de Where-Object; digite where.exe para usar a ferramenta do CMD. | where git | Get-Command git | command -v git |
Variáveis de ambiente
| Tarefa | CMD (Prompt de Comando) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Listar todas as variáveis # | set | Get-ChildItem Env: | env |
| Ler uma variável # | echo %PATH% | $env:PATH | echo "$PATH" |
| Definir para esta sessão # CMD: sem espaços em volta do =, senão eles passam a fazer parte do nome e do valor. | set MY_VAR=hello | $env:MY_VAR = 'hello' | export MY_VAR=hello |
| Definir permanentemente (para o seu usuário) # setx e SetEnvironmentVariable afetam só janelas novas, não a atual. O setx corta valores com mais de 1024 caracteres, então não o use para editar o PATH. | setx MY_VAR hello | [Environment]::SetEnvironmentVariable('MY_VAR','hello','User') | echo 'export MY_VAR=hello' >> ~/.bashrc |
| Remover uma variável # | set MY_VAR= | Remove-Item Env:MY_VAR | unset MY_VAR |
| Adicionar uma pasta ao PATH (sessão) # O PowerShell 7 no Linux/macOS separa o PATH com : em vez de ;. [IO.Path]::PathSeparator dá o separador certo. | set PATH=%PATH%;C:\tools | $env:PATH += ';C:\tools' | export PATH="$PATH:/opt/tools" |
| Definir só para um comando # | Sem comando nativo | $env:DEBUG = '1'; ./app; Remove-Item Env:DEBUG | DEBUG=1 ./app |
Processos
| Tarefa | CMD (Prompt de Comando) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Listar processos # | tasklist | Get-Process | ps aux |
| Encontrar um processo pelo nome # | tasklist /FI "IMAGENAME eq chrome.exe" | Get-Process chrome | pgrep -a chrome |
| Encerrar pelo ID do processo # Sem /F ou -Force, o Windows pede ao processo que feche. kill envia SIGTERM; kill -9 força. | taskkill /PID 1234 /F | Stop-Process -Id 1234 -Force | kill 1234 |
| Encerrar pelo nome # | taskkill /IM notepad.exe /F | Stop-Process -Name notepad | pkill notepad |
| Iniciar um programa # O "" vazio no start é o título da janela; sem ele, um caminho de programa entre aspas é tomado como título. | start "" notepad.exe | Start-Process notepad | gedit & |
| Executar elevado (como admin/root) # Use powershell em vez de pwsh para o Windows PowerShell 5.1. O Windows 11 24H2 ou posterior também pode ativar um comando sudo integrado nas Configurações. | runas /user:Administrator cmd | Start-Process pwsh -Verb RunAs | sudo command |
| Os 10 processos que mais usam CPU # CPU no Get-Process é o total de segundos de processador desde o início, não a % atual. | Sem comando nativo | Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 | ps aux --sort=-%cpu | head |
| O que está usando uma porta # Get-NetTCPConnection só existe no Windows. A última coluna do netstat -ano é o PID: procure-o com tasklist /FI "PID eq 1234". | netstat -ano | findstr :8080 | Get-NetTCPConnection -LocalPort 8080 | sudo ss -ltnp | grep :8080 |
Rede
| Tarefa | CMD (Prompt de Comando) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Mostrar endereços IP # Get-NetIPAddress e os outros cmdlets Net* só existem no Windows (módulo NetTCPIP). | ipconfig /all | Get-NetIPAddress | ip addr |
| Pingar um host # O ping do Windows para depois de 4 por padrão; o ping do Linux roda até Ctrl+C. | ping -n 4 example.com | Test-Connection example.com -Count 4 | ping -c 4 example.com |
| Testar uma porta TCP # Test-NetConnection só existe no Windows. No PowerShell 7: Test-Connection example.com -TcpPort 443. | Sem comando nativo | Test-NetConnection example.com -Port 443 | nc -zv example.com 443 |
| Consulta DNS # Resolve-DnsName só existe no Windows; o nslookup existe nos três. | nslookup example.com | Resolve-DnsName example.com | dig example.com |
| Rastrear rota # | tracert example.com | Test-NetConnection example.com -TraceRoute | traceroute example.com |
| Limpar o cache de DNS # A linha do bash vale para sistemas com systemd-resolved. | ipconfig /flushdns | Clear-DnsClientCache | sudo resolvectl flush-caches |
| HTTP GET (chamada de API) # Invoke-RestMethod converte JSON em objetos; Invoke-WebRequest retorna status, cabeçalhos e conteúdo bruto. | curl.exe https://api.example.com/items | Invoke-RestMethod https://api.example.com/items | curl https://api.example.com/items |
| Baixar um arquivo # O curl.exe vem com o Windows 10 1803 ou posterior. No Windows PowerShell 5.1, adicione -UseBasicParsing ao Invoke-WebRequest em máquinas sem o Internet Explorer configurado. | curl.exe -L -o file.zip https://example.com/file.zip | Invoke-WebRequest https://example.com/file.zip -OutFile file.zip | curl -LO https://example.com/file.zip |
| POST de JSON # O CMD não tem aspas simples, então as aspas duplas internas são escapadas com barras invertidas para o curl.exe. | curl.exe -X POST -H "Content-Type: application/json" -d "{\"a\":1}" https://api.example.com | Invoke-RestMethod https://api.example.com -Method Post -ContentType 'application/json' -Body (@{a=1} | ConvertTo-Json) | curl -X POST -H 'Content-Type: application/json' -d '{"a":1}' https://api.example.com |
| SSH para um servidor # O cliente OpenSSH vem instalado por padrão no Windows 10 1809+ e no Windows 11. | ssh user@host | ssh user@host | ssh user@host |
Serviços e sistema
| Tarefa | CMD (Prompt de Comando) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Listar serviços # No Windows PowerShell 5.1, sc é um alias de Set-Content: digite sc.exe. O PowerShell 6+ removeu esse alias. | sc query | Get-Service | systemctl list-units --type=service |
| Status de um serviço # | sc query Spooler | Get-Service Spooler | systemctl status nginx |
| Iniciar / parar um serviço # | net start Spooler
net stop Spooler | Start-Service Spooler
Stop-Service Spooler | sudo systemctl start nginx
sudo systemctl stop nginx |
| Reiniciar um serviço # | net stop Spooler && net start Spooler | Restart-Service Spooler | sudo systemctl restart nginx |
| Iniciar com o sistema # O sc.exe precisa do espaço depois de start= e de nenhum espaço antes. | sc config Spooler start= auto | Set-Service Spooler -StartupType Automatic | sudo systemctl enable nginx |
| Informações do sistema e do hardware # | systeminfo | Get-ComputerInfo | uname -a; cat /etc/os-release |
| Nome do computador # | hostname | $env:COMPUTERNAME | hostname |
| Usuário atual # Também $env:USERNAME no PowerShell no Windows. | whoami | whoami | whoami |
| Espaço livre em disco # Versões mais antigas do Windows exigem um prompt elevado para o fsutil. Get-Volume (só Windows) também mostra o tamanho e o espaço livre. | fsutil volume diskfree C: | Get-PSDrive -PSProvider FileSystem | df -h |
| Tempo ligado (uptime) # Get-Uptime é do PowerShell 6+. No 5.1: (Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime. | systeminfo | find "Boot Time" | Get-Uptime | uptime |
| Reiniciar agora # | shutdown /r /t 0 | Restart-Computer | sudo reboot |
| Limpar a tela # cls e clear funcionam no PowerShell no Windows. | cls | Clear-Host | clear |
| Histórico de comandos # Get-History cobre só esta sessão. O PSReadLine guarda o histórico mais antigo no arquivo em (Get-PSReadLineOption).HistorySavePath; Ctrl+R pesquisa nele nos três shells. | doskey /history | Get-History | history |
| Ajuda de um comando # Execute Update-Help uma vez (elevado no 5.1) para baixar a ajuda completa do PowerShell. | dir /? | Get-Help Get-ChildItem -Examples | man ls |
| Data atual # %date% segue o formato regional da máquina, então scripts que fazem parse dele quebram em outras localidades. | echo %date% | Get-Date -Format 'yyyy-MM-dd' | date +%F |
| Esperar 5 segundos # | timeout /t 5 | Start-Sleep -Seconds 5 | sleep 5 |
| Copiar a saída para a área de transferência # macOS: pbcopy. Wayland: wl-copy. Get-Clipboard lê de volta no PowerShell. | dir | clip | Get-ChildItem -Name | Set-Clipboard | ls | xclip -selection clipboard |
Pipe de objetos vs texto
| Tarefa | CMD (Prompt de Comando) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Escolher colunas / propriedades # O PowerShell passa objetos .NET pelo pipe, então você escolhe as propriedades pelo nome em vez de fazer parse de colunas. | Sem comando nativo | Get-Process | Select-Object Name, Id, WS | ps -eo comm,pid,rss |
| Filtrar linhas por um valor # O PowerShell entende literais como 500MB e 1GB. O awk compara a coluna 6 (RSS em KB). | tasklist | findstr chrome | Get-Process | Where-Object WS -gt 500MB | ps aux | awk '$6 > 500000' |
| Fazer algo para cada item # $_ (ou $PSItem) é o objeto atual. Em um arquivo .bat, escreva %%f em vez de %f. | for %f in (*.txt) do echo %f | Get-ChildItem *.txt | ForEach-Object { $_.Name } | for f in *.txt; do echo "$f"; done |
| Ver quais propriedades um objeto tem # O comando de descoberta mais útil do PowerShell; experimente também | Format-List *. | Sem comando nativo | Get-Process | Get-Member | Sem comando nativo |
| Fazer parse de JSON # Use -Raw para o arquivo chegar como uma única string; ConvertTo-Json -Depth 10 para a saída (a profundidade padrão é 2). | Sem comando nativo | Get-Content data.json -Raw | ConvertFrom-Json | jq . data.json |
| Ler e filtrar um CSV # Os valores do Import-Csv são strings; converta com [int] para comparações numéricas. | Sem comando nativo | Import-Csv users.csv | Where-Object { [int]$_.Age -gt 30 } | awk -F, 'NR>1 && $3 > 30' users.csv |
| Exportar para CSV # -NoTypeInformation é o padrão no PowerShell 6+, mas é necessário no 5.1. | Sem comando nativo | Get-Process | Export-Csv procs.csv -NoTypeInformation | ps -eo pid,comm --no-headers | awk '{print $1","$2}' > procs.csv |
| Contar, somar, média # | find /c /v "" file.txt | Get-ChildItem -File | Measure-Object Length -Sum -Average | ls -l | awk '{s+=$5} END {print s}' |
Scripts: variáveis, condicionais, loops, funções
| Tarefa | CMD (Prompt de Comando) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Definir uma variável # bash: sem espaços em volta do = (name = Ada executa um comando chamado name). | set name=Ada | $name = 'Ada' | name=Ada |
| Usar uma variável em uma string # | echo Hello %name% | "Hello $name" | echo "Hello $name" |
| Aritmética # O CMD e o bash só fazem contas com inteiros; o PowerShell usa números do .NET. | set /a n=5*3 | $n = 5 * 3 | n=$((5 * 3)) |
| Ler a entrada do usuário # | set /p name=Name: | $name = Read-Host 'Name' | read -rp 'Name: ' name |
| Argumentos do script # Em arquivos .bat, %~1 remove as aspas em volta. Um bloco param() dá aos scripts do PowerShell parâmetros nomeados e tipados. | %1 %2 … %* | $args[0] or param($Path) | $1 $2 … "$@" |
| If / else com uma string # Os operadores de comparação do PowerShell são palavras: -eq -ne -gt -lt -like -match. = e > são atribuição e redirecionamento. | if "%a%"=="yes" (echo on) else (echo off) | if ($a -eq 'yes') { 'on' } else { 'off' } | if [ "$a" = "yes" ]; then echo on; else echo off; fi |
| Comparar números # CMD: EQU NEQ LSS LEQ GTR GEQ. | if %n% GTR 5 echo big | if ($n -gt 5) { 'big' } | if (( n > 5 )); then echo big; fi |
| Se um arquivo existe # | if exist file.txt echo yes | if (Test-Path file.txt) { 'yes' } | if [ -f file.txt ]; then echo yes; fi |
| Código de saída do último programa # No PowerShell, $? é $true/$false para o último comando; $LASTEXITCODE é o código numérico do último programa nativo. | echo %ERRORLEVEL% | $LASTEXITCODE | echo $? |
| Executar o próximo comando só em caso de sucesso / falha # Os operadores de encadeamento && e || chegaram no PowerShell 7.0; o Windows PowerShell 5.1 os rejeita. | build && deploy
build || echo failed | build && deploy (PowerShell 7+)
build; if ($?) { deploy } (5.1) | build && deploy
build || echo failed |
| Loop sobre uma lista # | for %i in (a b c) do echo %i | foreach ($x in 'a','b','c') { $x } | for x in a b c; do echo "$x"; done |
| Loop de 1 a 5 # | for /l %i in (1,1,5) do echo %i | foreach ($i in 1..5) { $i } | for i in {1..5}; do echo "$i"; done |
| Loop sobre as linhas de um arquivo # | for /f "usebackq delims=" %l in ("file.txt") do echo %l | foreach ($line in Get-Content file.txt) { $line } | while IFS= read -r line; do echo "$line"; done < file.txt |
| Loop while # O CMD não tem while; use goto com um rótulo em um arquivo .bat. | :loop
set /a i+=1
if %i% lss 5 goto loop | while ($i -lt 5) { $i++ } | while [ "$i" -lt 5 ]; do i=$((i+1)); done |
| Definir e chamar uma função # Chame funções do PowerShell como comandos: Greet Ada, não Greet("Ada"). | call :greet Ada
goto :eof
:greet
echo Hello %~1
exit /b | function Greet($Name) { "Hello $Name" }
Greet Ada | greet() { echo "Hello $1"; }
greet Ada |
| Guardar a saída de um comando em uma variável # | for /f "delims=" %i in ('hostname') do set h=%i | $h = hostname | h=$(hostname) |
| Descartar a saída # | command >nul 2>&1 | command *> $null | command >/dev/null 2>&1 |
| Comentário # | rem comment
:: comment | # comment
<# block #> | # comment |
| Arquivo de script e como executá-lo # O PowerShell não executa scripts da pasta atual sem .\ e pode bloqueá-los de vez: veja a política de execução abaixo. | script.bat | .\script.ps1 | chmod +x script.sh && ./script.sh |
Armadilhas dos aliases do PowerShell: ls, curl, wget, sc, where
O PowerShell vem com aliases que parecem comandos do Unix ou do CMD, mas executam cmdlets com parâmetros diferentes. Quais existem depende da edição e do sistema operacional. Get-Alias name mostra para onde um nome aponta na sua sessão.
| Você digita | Windows PowerShell 5.1 | PowerShell 7 no Windows | PowerShell 7 no Linux/macOS |
|---|---|---|---|
curlDigite curl.exe no 5.1 para usar o curl de verdade. As flags dele (-X, -H, -d) não significam nada para o Invoke-WebRequest. | Invoke-WebRequest | não é alias: executa o curl.exe | curl nativo |
wgetUse Invoke-WebRequest url -OutFile nome, ou curl.exe -LO url. | Invoke-WebRequest | não é alias (o Windows não tem wget por padrão) | wget nativo, se instalado |
ls, dirFlags como ls -la falham no Windows: use Get-ChildItem -Force. | Get-ChildItem | Get-ChildItem | ls = ls nativo; dir = Get-ChildItem |
cat, type | Get-Content | Get-Content | cat = cat nativo; type = Get-Content |
cp, mv, rm, rmdirrm -rf não é PowerShell válido: use Remove-Item -Recurse -Force. | Copy-Item, Move-Item, Remove-Item | os mesmos cmdlets | comandos nativos |
ps, kill | Get-Process, Stop-Process | os mesmos cmdlets | comandos nativos |
sort, tee, diffdiff a b no PowerShell no Windows compara objetos, não as linhas de dois arquivos. | Sort-Object, Tee-Object, Compare-Object | os mesmos cmdlets | comandos nativos |
scNo 5.1, sc query grava um arquivo chamado query. Use sc.exe. | Set-Content | não é alias: executa o sc.exe | n/d |
whereUse where.exe para encontrar um programa, ou Get-Command. | Where-Object | Where-Object | Where-Object |
echoecho -n não suprime a quebra de linha; use Write-Host -NoNewline. | Write-Output | Write-Output | Write-Output |
man | help | help | man nativo |
Aspas e escape
A maioria dos bugs do tipo “funciona em um shell e falha em outro” é por causa de aspas. O caractere de escape é diferente em cada shell.
| O quê | CMD | PowerShell | Bash |
|---|---|---|---|
| String literal (sem expansão) | Não há aspas literais: %VAR% é expandida mesmo dentro de "…" | 'Cost: $5' | 'Cost: $5' |
| String com variáveis | "Hello %name%" | "Hello $name, it is $(Get-Date -Format t)" | "Hello $name, it is $(date +%R)" |
| Caractere de escape | ^ (ex.: ^& ^| ^>) | ` crase (ex.: `n nova linha, `t tab, `$ $ literal) | \ barra invertida |
| Aspas dentro de uma string entre aspas | "" dentro de "…" em muitos programas; varia conforme o programa | 'It''s' ou "Say `"hi`"" | 'It'\''s' ou "Say \"hi\"" |
| Continuação de linha | ^ no fim da linha | ` no fim da linha (ou termine a linha com | ) | \ no fim da linha |
| % ou $ literal em um script | %% em um arquivo .bat | '$' entre aspas simples ou `$ | '$' entre aspas simples ou \$ |
| Passar argumentos intactos para um programa nativo | (não é necessário) | --% faz o PowerShell parar de interpretar o resto da linha | (não é necessário) |
A passagem de aspas para programas nativos (curl.exe, git, node) mudou no PowerShell 7.3: argumentos com aspas duplas internas agora são passados como escritos, o que é controlado por $PSNativeCommandArgumentPassing. No Windows PowerShell 5.1, o mesmo corpo JSON muitas vezes precisa ter as aspas internas escapadas duas vezes, e é por isso que muita gente passa a usar Invoke-RestMethod com ConvertTo-Json.
Política de execução: “a execução de scripts foi desabilitada neste sistema”
O PowerShell se recusa a executar arquivos .ps1 quando a política de execução é Restricted, que é o padrão efetivo do Windows PowerShell nas edições cliente do Windows (Windows 10 e 11). O Windows Server usa RemoteSigned por padrão: scripts locais rodam, os baixados precisam ser assinados ou desbloqueados. No Linux e no macOS a política é Unrestricted e não pode ser alterada.
Get-ExecutionPolicy -Listmostra a política em cada escopo; vale o escopo definido mais específico (a Política de Grupo se sobrepõe a todos).Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUserpermite que seus próprios scripts rodem sem direitos de administrador.Unblock-File .\script.ps1remove a marca de “baixado da internet” de um script em que você confia.pwsh -ExecutionPolicy Bypass -File script.ps1(oupowershellno 5.1) aplica uma política só a uma sessão.
A política de execução é uma trava contra executar scripts por acidente, não uma barreira de segurança: qualquer pessoa pode colar o conteúdo do script no console.
Windows PowerShell 5.1 vs PowerShell 7
- Dois programas:
powershell.exeé o Windows PowerShell 5.1, que vem com o Windows e não recebe mais novos recursos.pwshé o PowerShell 7, instalado separadamente e multiplataforma; os dois podem conviver lado a lado. - Operadores adicionados no 7.0:
&&e||entre comandos, o ternário$a ? 'yes' : 'no'e a coalescência nula??/??=. - Codificação de arquivos: no 5.1,
>eOut-Filegravam em UTF-16 LE, eSet-Contentusa a página de código ANSI. O PowerShell 7 grava UTF-8 sem BOM em todos os casos, que é o que o Git, as ferramentas do Linux e a maioria dos editores esperam. - Aliases: o 7 removeu
curl,wgetescno Windows e, no Linux/macOS, deixals,cp,rm,cat,pse outros para os comandos nativos (tabela acima). - Módulos que faltam: cmdlets exclusivos do Windows, como
Get-NetIPAddress,Test-NetConnectioneResolve-DnsName, funcionam no PowerShell 7 no Windows, mas não existem no Linux nem no macOS.
Usando bash no Windows: WSL
O Subsistema do Windows para Linux executa uma distribuição Linux de verdade ao lado do Windows, então todo comando bash da coluna da direita funciona como está escrito. wsl --install em um prompt elevado o instala com Ubuntu por padrão (Windows 10 versão 2004 ou posterior e Windows 11); wsl -l -v lista as distribuições instaladas.
- Execute um comando Linux a partir do CMD ou do PowerShell:
wsl ls -la, ou use pipe entre os dois:dir | wsl grep txt. - As unidades do Windows aparecem dentro do Linux em
/mnt/c; os arquivos do Linux podem ser acessados pelo Explorador em\\wsl.localhost\Ubuntu(builds mais antigas:\\wsl$\Ubuntu). - Mantenha os projetos dentro do sistema de arquivos do Linux (~/), não em /mnt/c: o acesso a arquivos através dessa fronteira é bem mais lento.
Para o lado Linux em detalhes, veja o guia rápido de comandos Linux.
Encontrou um problema ou algo que poderia ser melhor? Lemos todas as mensagens e corrigimos rápido.
Esta tabela CMD vs PowerShell vs Bash mostra a mesma tarefa no Prompt de Comando do Windows, no PowerShell e no bash numa única linha: listar e copiar arquivos, procurar texto em arquivos (o equivalente ao grep no PowerShell é o Select-String), variáveis de ambiente, processos, rede, serviços, leitura e gravação de conteúdo de arquivos e scripts com variáveis, condicionais, loops e funções. Busque um comando de qualquer um dos três shells e você verá os equivalentes, cada um com um botão de copiar.
O guia também cobre o que costuma dar errado quando você passa de um para outro: aliases do PowerShell que parecem comandos Unix mas não são (curl e wget no Windows PowerShell 5.1, ls e rm em qualquer Windows), caracteres de aspas e escape diferentes, o erro de política de execução que bloqueia scripts .ps1 e as diferenças entre o Windows PowerShell 5.1 e o PowerShell 7. Os comandos do PowerShell funcionam nas duas versões, a não ser que uma nota diga o contrário; quando não existe equivalente no CMD, a tabela diz isso em vez de inventar um.
Como usar
- Busque o comando que você conhece, em qualquer shell (por exemplo “grep”, “findstr” ou “Select-String”), ou a tarefa (“encerrar processo”, “variável de ambiente”).
- Leia a linha para ver o equivalente nos outros dois shells e clique em Copiar ao lado do que você precisa.
- Confira a nota abaixo do nome da tarefa: ela sinaliza diferenças de versão (PowerShell 5.1 vs 7) e cmdlets exclusivos do Windows.
- Role até as seções de aliases, aspas e política de execução se um comando se comportar de um jeito diferente do esperado.
- Use Imprimir / Salvar como PDF para ter uma cópia na mesa; a página também funciona no celular, onde cada linha vira um cartão.
Perguntas frequentes
Qual é o equivalente ao grep no PowerShell?
Select-String. Pesquise num arquivo com Select-String -Path app.log -Pattern error ou filtre a saída de um comando com ipconfig | Select-String IPv4. Por padrão, ele não diferencia maiúsculas de minúsculas (adicione -CaseSensitive), usa expressões regulares do .NET, e -NotMatch equivale ao grep -v. Para buscas recursivas, passe Get-ChildItem -Recurse -Filter *.log pelo pipe para o Select-String. O alias curto dele é sls.
Por que o curl se comporta de forma estranha no PowerShell?
No Windows PowerShell 5.1, curl e wget são aliases de Invoke-WebRequest, então flags do curl como -X, -H e -d são rejeitadas ou significam outra coisa. Digite curl.exe para rodar o curl de verdade, que vem com o Windows 10 1803 e posteriores. O PowerShell 7 removeu esses aliases, então lá curl roda o curl.exe. No Linux e no macOS, curl nunca foi um alias.
O PowerShell é melhor que o CMD?
Para qualquer coisa além de rodar um programa ou um arquivo batch curto, sim. O PowerShell passa objetos estruturados pelo pipe em vez de texto, então você filtra e ordena pelo nome da propriedade (Where-Object, Sort-Object) em vez de analisar colunas, e tem funções de verdade, tratamento de erros, suporte a JSON e CSV e execução remota. O CMD ainda serve para arquivos .bat legados e alguns instaladores, e toda ferramenta do CMD (ipconfig, robocopy, netstat) também pode ser executada a partir do PowerShell.
Como corrijo “a execução de scripts foi desabilitada neste sistema”?
Isso é a política de execução, que vem como Restricted por padrão nas edições cliente do Windows 10 e 11. Rode Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser no PowerShell (não precisa de administrador). Aí os seus próprios scripts rodam, e scripts baixados da internet precisam ser assinados ou desbloqueados com Unblock-File. Get-ExecutionPolicy -List mostra o que está definido em cada escopo; uma configuração de Política de Grupo sobrepõe qualquer coisa que você mesmo defina.
Posso rodar comandos bash no Windows?
Sim, com o Subsistema do Windows para Linux (WSL). Rode wsl --install num prompt com privilégios elevados (Windows 10 versão 2004 ou posterior, ou Windows 11) para instalar o Ubuntu, depois abra-o pelo menu Iniciar ou rode comandos avulsos no CMD ou no PowerShell com wsl seguido do comando, como wsl grep -rn TODO. O Git for Windows também inclui o Git Bash, um bash mais leve com as ferramentas Unix mais comuns.
Qual é a diferença entre o Windows PowerShell e o PowerShell 7?
O Windows PowerShell 5.1 (powershell.exe) vem embutido no Windows e só recebe correções. O PowerShell 7 (pwsh) é a versão atual, multiplataforma, que roda no Windows, Linux e macOS e é instalada à parte; os dois podem ser instalados juntos. A versão 7 adiciona && e || entre comandos, os operadores ternário e ??, grava arquivos em UTF-8 por padrão e remove alguns aliases confusos, como curl e wget.
Objetos vs. texto: a ideia que faz o PowerShell fazer sentido
No CMD e no bash, um pipe transporta texto. Para achar o processo que usa mais memória no bash, você pega a coluna certa da saída do ps com sort -k ou awk, e o comando quebra se o layout das colunas mudar. No PowerShell, o pipe transporta objetos com propriedades nomeadas, então a mesma tarefa fica Get-Process | Sort-Object WS -Descending | Select-Object -First 1. Nada é analisado como texto, e os nomes das propriedades são os mesmos em qualquer máquina.
A consequência prática é outro jeito de descobrir as coisas. No bash, você lê uma man page para conhecer o formato da saída; no PowerShell, você passa qualquer comando pelo pipe para o Get-Member para ver quais propriedades e métodos os objetos têm, depois filtra com Where-Object e escolhe os campos com Select-Object. Só quando a saída chega à tela ou a um arquivo o PowerShell a transforma em texto.
Programas nativos como ipconfig, git ou curl.exe continuam gerando texto no PowerShell, então Select-String e -match funcionam neles como o grep funcionaria. O código de saída deles fica em $LASTEXITCODE, não em $?.
Como traduzir um script entre os três shells
A tradução linha a linha funciona para scripts simples, mas algumas diferenças pegam quase todo mundo:
• Operadores de comparação: o CMD usa == para strings e EQU, GTR, LSS para números; o PowerShell usa -eq, -gt, -lt, -like e -match (um > solto é redirecionamento); o bash usa = dentro de [ ] para strings e -gt ou (( )) para números.
• Variáveis: %name% no CMD (e !name! dentro de loops depois de setlocal EnableDelayedExpansion), $name no PowerShell, $name no bash, sem espaços em volta do = na atribuição.
• Loops em arquivos .bat dobram o sinal de porcentagem: for %%f in (*.txt) dentro de um arquivo, for %f no prompt.
• Caminhos: o PowerShell aceita tanto / quanto \ no Windows; o bash no Linux precisa de /. Variáveis de ambiente não diferenciam maiúsculas de minúsculas no Windows e diferenciam no Linux.
• Erros: o CMD continua depois de uma falha a não ser que você verifique %ERRORLEVEL%; o bash continua a não ser que haja set -e; o PowerShell continua após erros não fatais a não ser que $ErrorActionPreference = 'Stop'.
Quando um script precisa rodar no Windows e no Linux, o PowerShell 7 ou o bash no WSL evitam manter duas cópias.
Ferramentas grátis relacionadas
- Guia rápido de comandos Linux — Comandos Linux por tarefa, de arquivos e permissões a rede, systemd e processamento de texto. Cada entrada tem opções, exemplos para copiar e notas sobre o macOS.
- Atalhos de teclado do Windows — Todos os atalhos do Windows 11 numa lista pesquisável e para imprimir: tecla Windows, Ajuste, áreas de trabalho, capturas de tela, Explorador de Arquivos.
- Atalhos de teclado do Mac — Todos os atalhos do macOS com os símbolos ⌘ ⌥ ⌃ ⇧ explicados: capturas de tela, organização de janelas, Finder, Safari e caracteres especiais.
- curl para código — Cole um comando curl, inclusive o “Copy as cURL” do Chrome, e receba a mesma requisição em Python, JavaScript, Node, Go, PHP, Ruby, Java, C#, wget ou HTTPie.
- Guia rápido de Git — Comandos do Git organizados pelo que você quer fazer: desfazer o último commit, renomear uma branch, apagar uma branch remota. switch/restore modernos com os equivalentes clássicos e alertas de perigo.