CMD vs PowerShell vs Bash — Comandi equivalenti
La stessa operazione nel Prompt dei comandi, in PowerShell e in bash, fianco a fianco: file, grep, variabili d'ambiente, processi, rete, servizi e scripting.
Ultima verifica: 2026-10-18 su il riferimento di Microsoft Learn per PowerShell 7.6 e Windows PowerShell 5.1, il riferimento dei comandi di Windows e il manuale di GNU Bash 5.2.
File e cartelle
| Attività | CMD (Prompt dei comandi) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Elencare i file # Alias di PowerShell: gci, dir e, su Windows, ls. | dir | Get-ChildItem | ls -l |
| Elencare tutti i file in modo ricorsivo # | dir /s /b | Get-ChildItem -Recurse -File | find . -type f |
| Mostrare la directory corrente # In CMD, cd senza argomenti stampa la directory corrente. Alias di PowerShell: pwd, gl; c'è anche la variabile $PWD. | cd | Get-Location | pwd |
| Cambiare directory # In CMD serve /d per cambiare anche unità oltre alla cartella. Alias di PowerShell: cd, sl, chdir. | cd /d D:\work | Set-Location D:\work | cd /home/me/work |
| Andare alla directory home # | cd %USERPROFILE% | Set-Location ~ | cd ~ |
| Creare una cartella (con le cartelle padre) # In CMD mkdir crea le cartelle intermedie quando le estensioni dei comandi sono attive (impostazione predefinita). In PowerShell, mkdir è una funzione che richiama New-Item -ItemType Directory. | mkdir a\b\c | New-Item -ItemType Directory -Path a\b\c | mkdir -p a/b/c |
| Creare un file vuoto # | type nul > file.txt | New-Item file.txt | touch file.txt |
| Copiare un file # | copy src.txt dst.txt | Copy-Item src.txt dst.txt | cp src.txt dst.txt |
| Copiare una cartella in modo ricorsivo # Funziona anche xcopy src dst /E /I; robocopy è lo strumento supportato e può riprendere e ritentare. | robocopy src dst /E | Copy-Item src dst -Recurse | cp -r src dst |
| Creare una copia speculare esatta di una cartella Pericoloso # Attenzione: Entrambi eliminano dalla destinazione i file che non sono nell'origine. Se inverti i due percorsi, cancelli la cartella che volevi conservare. robocopy /L e rsync -n fanno una prova a vuoto. | robocopy src dst /MIR | (no cmdlet; call robocopy) | rsync -a --delete src/ dst/ |
| Spostare un file # | move a.txt archive\ | Move-Item a.txt archive\ | mv a.txt archive/ |
| Rinominare un file # | ren old.txt new.txt | Rename-Item old.txt new.txt | mv old.txt new.txt |
| Eliminare un file # | del file.txt | Remove-Item file.txt | rm file.txt |
| Eliminare una cartella e il suo contenuto Pericoloso # Attenzione: Niente Cestino e nessuna conferma con /q, -Force o -f. Controlla prima il percorso; in PowerShell aggiungi -WhatIf per vedere cosa verrebbe rimosso. | rmdir /s /q folder | Remove-Item folder -Recurse -Force | rm -rf folder |
| Creare un collegamento simbolico # Su Windows, creare collegamenti simbolici richiede un prompt con privilegi elevati, a meno che non sia attiva la Modalità sviluppatore. Attenzione all'ordine degli argomenti: prima il collegamento in CMD/PowerShell, prima la destinazione in 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 |
| Modificare i permessi dei file # Windows usa le ACL, non i bit rwx; icacls di solito è più semplice di Set-Acl. | icacls file.txt /grant alice:F | Get-Acl / Set-Acl | chmod 644 file.txt |
| Checksum di un file (SHA-256) # Get-FileHash usa SHA256 per impostazione predefinita; -Algorithm MD5 o SHA1 per gli altri. macOS: shasum -a 256. | certutil -hashfile file.iso SHA256 | Get-FileHash file.iso | sha256sum file.iso |
| Creare un file zip # tar.exe (bsdtar) è incluso in Windows 10 1803 e successivi; -a sceglie il formato dall'estensione .zip. | tar -a -c -f out.zip folder | Compress-Archive -Path folder -DestinationPath out.zip | zip -r out.zip folder |
| Estrarre un file zip # | tar -xf out.zip | Expand-Archive out.zip -DestinationPath dest | unzip out.zip -d dest |
Leggere e scrivere il contenuto dei file
| Attività | CMD (Prompt dei comandi) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Stampare un file # Alias di PowerShell: gc, type e, su Windows, cat. | type file.txt | Get-Content file.txt | cat file.txt |
| Scorrere un file pagina per pagina # | more file.txt | Get-Content file.txt | Out-Host -Paging | less file.txt |
| Prime 10 righe # -Head è un alias di -TotalCount. | Nessun comando integrato | Get-Content file.txt -TotalCount 10 | head -n 10 file.txt |
| Ultime 10 righe # | Nessun comando integrato | Get-Content file.txt -Tail 10 | tail -n 10 file.txt |
| Seguire un file di log # | Nessun comando integrato | Get-Content app.log -Tail 10 -Wait | tail -f app.log |
| Scrivere testo in un file (sovrascrivendo) # In CMD, uno spazio prima di > finisce nel file. In Windows PowerShell 5.1, > scrive in UTF-16 LE; PowerShell 7 scrive in UTF-8 senza BOM. Set-Content -Encoding utf8 è esplicito in entrambi. | echo hello> file.txt | 'hello' | Set-Content file.txt | echo hello > file.txt |
| Aggiungere testo in fondo a un file # | echo hello>> file.txt | Add-Content file.txt 'hello' | echo hello >> file.txt |
| Contare le righe # | find /c /v "" file.txt | (Get-Content file.txt).Count | wc -l file.txt |
| Confrontare due file # In PowerShell su Windows, diff è un alias di Compare-Object, non un diff testuale. | fc a.txt b.txt | Compare-Object (Get-Content a.txt) (Get-Content b.txt) | diff a.txt b.txt |
| Ordinare le righe # | sort file.txt | Get-Content file.txt | Sort-Object | sort file.txt |
| Righe univoche # | Nessun comando integrato | Get-Content file.txt | Sort-Object -Unique | sort -u file.txt |
| Sostituire testo in un file # -replace usa le espressioni regolari; le parentesi leggono l'intero file prima che Set-Content lo riapra. Su macOS sed richiede -i ''. | Nessun comando integrato | (Get-Content f.txt) -replace 'old','new' | Set-Content f.txt | sed -i 's/old/new/g' f.txt |
Ricerca (equivalenti di grep)
| Attività | CMD (Prompt dei comandi) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Trovare testo nei file # Select-String per impostazione predefinita non distingue maiuscole e minuscole (usa -CaseSensitive per cambiarlo). Per le sottocartelle: 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' . |
| Filtrare l'output di un comando # | ipconfig | findstr IPv4 | ipconfig | Select-String IPv4 | ip a | grep inet |
| Righe che NON corrispondono # | findstr /v "DEBUG" app.log | Select-String -Path app.log -Pattern DEBUG -NotMatch | grep -v DEBUG app.log |
| Cercare con un'espressione regolare # findstr supporta solo un piccolo sottoinsieme delle regex (niente |, niente {n}). Select-String usa le espressioni regolari .NET. | findstr /r "^ERR.*timeout" app.log | Select-String -Path app.log -Pattern '^ERR.*timeout' | grep -E '^ERR.*timeout' app.log |
| Trovare file per nome # | dir /s /b *.log | Get-ChildItem -Recurse -Filter *.log | find . -name '*.log' |
| Trovare dove si trova un programma # In PowerShell, where è un alias di Where-Object; digita where.exe per usare lo strumento di CMD. | where git | Get-Command git | command -v git |
Variabili d'ambiente
| Attività | CMD (Prompt dei comandi) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Elencare tutte le variabili # | set | Get-ChildItem Env: | env |
| Leggere una variabile # | echo %PATH% | $env:PATH | echo "$PATH" |
| Impostare per questa sessione # CMD: niente spazi attorno a =, altrimenti diventano parte del nome e del valore. | set MY_VAR=hello | $env:MY_VAR = 'hello' | export MY_VAR=hello |
| Impostare in modo permanente (per il tuo utente) # setx e SetEnvironmentVariable valgono solo per le nuove finestre, non per quella corrente. setx tronca i valori più lunghi di 1024 caratteri, quindi non usarlo per modificare PATH. | setx MY_VAR hello | [Environment]::SetEnvironmentVariable('MY_VAR','hello','User') | echo 'export MY_VAR=hello' >> ~/.bashrc |
| Rimuovere una variabile # | set MY_VAR= | Remove-Item Env:MY_VAR | unset MY_VAR |
| Aggiungere una cartella al PATH (sessione) # PowerShell 7 su Linux/macOS separa il PATH con : invece di ;. [IO.Path]::PathSeparator restituisce quello giusto. | set PATH=%PATH%;C:\tools | $env:PATH += ';C:\tools' | export PATH="$PATH:/opt/tools" |
| Impostare solo per un comando # | Nessun comando integrato | $env:DEBUG = '1'; ./app; Remove-Item Env:DEBUG | DEBUG=1 ./app |
Processi
| Attività | CMD (Prompt dei comandi) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Elencare i processi # | tasklist | Get-Process | ps aux |
| Trovare un processo per nome # | tasklist /FI "IMAGENAME eq chrome.exe" | Get-Process chrome | pgrep -a chrome |
| Terminare per ID di processo # Senza /F o -Force, Windows chiede al processo di chiudersi. kill invia SIGTERM; kill -9 forza la chiusura. | taskkill /PID 1234 /F | Stop-Process -Id 1234 -Force | kill 1234 |
| Terminare per nome # | taskkill /IM notepad.exe /F | Stop-Process -Name notepad | pkill notepad |
| Avviare un programma # Le virgolette vuote "" in start sono il titolo della finestra; senza di esse, il percorso di un programma tra virgolette viene preso come titolo. | start "" notepad.exe | Start-Process notepad | gedit & |
| Eseguire con privilegi elevati (come admin/root) # Usa powershell invece di pwsh per Windows PowerShell 5.1. Windows 11 24H2 e successivi possono anche abilitare un comando sudo integrato nelle Impostazioni. | runas /user:Administrator cmd | Start-Process pwsh -Verb RunAs | sudo command |
| I 10 processi che usano più CPU # La CPU in Get-Process è il totale dei secondi di processore dall'avvio, non la % attuale. | Nessun comando integrato | Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 | ps aux --sort=-%cpu | head |
| Cosa sta usando una porta # Get-NetTCPConnection è solo per Windows. L'ultima colonna di netstat -ano è il PID: cercalo con tasklist /FI "PID eq 1234". | netstat -ano | findstr :8080 | Get-NetTCPConnection -LocalPort 8080 | sudo ss -ltnp | grep :8080 |
Rete
| Attività | CMD (Prompt dei comandi) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Mostrare gli indirizzi IP # Get-NetIPAddress e gli altri cmdlet Net* sono solo per Windows (modulo NetTCPIP). | ipconfig /all | Get-NetIPAddress | ip addr |
| Fare il ping di un host # Su Windows ping si ferma dopo 4 tentativi per impostazione predefinita; su Linux continua finché non premi Ctrl+C. | ping -n 4 example.com | Test-Connection example.com -Count 4 | ping -c 4 example.com |
| Testare una porta TCP # Test-NetConnection è solo per Windows. In PowerShell 7: Test-Connection example.com -TcpPort 443. | Nessun comando integrato | Test-NetConnection example.com -Port 443 | nc -zv example.com 443 |
| Ricerca DNS # Resolve-DnsName è solo per Windows; nslookup esiste su tutti e tre. | nslookup example.com | Resolve-DnsName example.com | dig example.com |
| Tracciare il percorso # | tracert example.com | Test-NetConnection example.com -TraceRoute | traceroute example.com |
| Svuotare la cache DNS # La riga bash vale per i sistemi con systemd-resolved. | ipconfig /flushdns | Clear-DnsClientCache | sudo resolvectl flush-caches |
| HTTP GET (chiamata API) # Invoke-RestMethod converte il JSON in oggetti; Invoke-WebRequest restituisce stato, intestazioni e contenuto grezzo. | curl.exe https://api.example.com/items | Invoke-RestMethod https://api.example.com/items | curl https://api.example.com/items |
| Scaricare un file # curl.exe è incluso in Windows 10 1803 e successivi. In Windows PowerShell 5.1, aggiungi -UseBasicParsing a Invoke-WebRequest sui computer in cui Internet Explorer non è configurato. | 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 di JSON # CMD non ha le virgolette singole, quindi per curl.exe le virgolette doppie interne vanno precedute da una barra rovesciata. | 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 |
| Connettersi a un server via SSH # Il client OpenSSH è installato per impostazione predefinita su Windows 10 1809+ e Windows 11. | ssh user@host | ssh user@host | ssh user@host |
Servizi e sistema
| Attività | CMD (Prompt dei comandi) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Elencare i servizi # In Windows PowerShell 5.1, sc è un alias di Set-Content: lì digita sc.exe. PowerShell 6+ ha rimosso quell'alias. | sc query | Get-Service | systemctl list-units --type=service |
| Stato di un servizio # | sc query Spooler | Get-Service Spooler | systemctl status nginx |
| Avviare / arrestare un servizio # | net start Spooler
net stop Spooler | Start-Service Spooler
Stop-Service Spooler | sudo systemctl start nginx
sudo systemctl stop nginx |
| Riavviare un servizio # | net stop Spooler && net start Spooler | Restart-Service Spooler | sudo systemctl restart nginx |
| Avvio automatico all'accensione # sc.exe richiede lo spazio dopo start= e nessuno spazio prima. | sc config Spooler start= auto | Set-Service Spooler -StartupType Automatic | sudo systemctl enable nginx |
| Informazioni su sistema operativo e hardware # | systeminfo | Get-ComputerInfo | uname -a; cat /etc/os-release |
| Nome del computer # | hostname | $env:COMPUTERNAME | hostname |
| Utente corrente # In PowerShell su Windows c'è anche $env:USERNAME. | whoami | whoami | whoami |
| Spazio libero su disco # Le versioni meno recenti di Windows richiedono un prompt con privilegi elevati per fsutil. Get-Volume (solo Windows) mostra anche dimensione e spazio libero. | fsutil volume diskfree C: | Get-PSDrive -PSProvider FileSystem | df -h |
| Tempo di attività # Get-Uptime è disponibile da PowerShell 6+. Nella 5.1: (Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime. | systeminfo | find "Boot Time" | Get-Uptime | uptime |
| Riavviare subito # | shutdown /r /t 0 | Restart-Computer | sudo reboot |
| Pulire lo schermo # In PowerShell su Windows funzionano sia cls sia clear. | cls | Clear-Host | clear |
| Cronologia dei comandi # Get-History copre solo questa sessione. PSReadLine conserva la cronologia precedente nel file indicato da (Get-PSReadLineOption).HistorySavePath; Ctrl+R la cerca in tutte e tre le shell. | doskey /history | Get-History | history |
| Guida di un comando # Esegui Update-Help una volta (con privilegi elevati nella 5.1) per scaricare la guida completa di PowerShell. | dir /? | Get-Help Get-ChildItem -Examples | man ls |
| Data corrente # %date% segue il formato regionale del computer, quindi gli script che lo analizzano non funzionano con impostazioni internazionali diverse. | echo %date% | Get-Date -Format 'yyyy-MM-dd' | date +%F |
| Attendere 5 secondi # | timeout /t 5 | Start-Sleep -Seconds 5 | sleep 5 |
| Copiare l'output negli appunti # macOS: pbcopy. Wayland: wl-copy. In PowerShell Get-Clipboard lo rilegge. | dir | clip | Get-ChildItem -Name | Set-Clipboard | ls | xclip -selection clipboard |
Pipe di oggetti e pipe di testo
| Attività | CMD (Prompt dei comandi) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Scegliere colonne / proprietà # PowerShell passa oggetti .NET nella pipe, quindi scegli le proprietà per nome invece di analizzare le colonne. | Nessun comando integrato | Get-Process | Select-Object Name, Id, WS | ps -eo comm,pid,rss |
| Filtrare le righe per valore # PowerShell capisce letterali come 500MB e 1GB. awk confronta la colonna 6 (RSS in KB). | tasklist | findstr chrome | Get-Process | Where-Object WS -gt 500MB | ps aux | awk '$6 > 500000' |
| Fare qualcosa per ogni elemento # $_ (o $PSItem) è l'oggetto corrente. In un file .bat scrivi %%f invece di %f. | for %f in (*.txt) do echo %f | Get-ChildItem *.txt | ForEach-Object { $_.Name } | for f in *.txt; do echo "$f"; done |
| Vedere quali proprietà ha un oggetto # Il comando di esplorazione più utile di PowerShell; prova anche | Format-List *. | Nessun comando integrato | Get-Process | Get-Member | Nessun comando integrato |
| Analizzare JSON # Usa -Raw in modo che il file arrivi come un'unica stringa; ConvertTo-Json -Depth 10 per l'output (la profondità predefinita è 2). | Nessun comando integrato | Get-Content data.json -Raw | ConvertFrom-Json | jq . data.json |
| Leggere e filtrare un CSV # I valori di Import-Csv sono stringhe; converti con [int] per i confronti numerici. | Nessun comando integrato | Import-Csv users.csv | Where-Object { [int]$_.Age -gt 30 } | awk -F, 'NR>1 && $3 > 30' users.csv |
| Esportare in CSV # -NoTypeInformation è predefinito in PowerShell 6+ ma necessario nella 5.1. | Nessun comando integrato | Get-Process | Export-Csv procs.csv -NoTypeInformation | ps -eo pid,comm --no-headers | awk '{print $1","$2}' > procs.csv |
| Conteggio, somma, media # | find /c /v "" file.txt | Get-ChildItem -File | Measure-Object Length -Sum -Average | ls -l | awk '{s+=$5} END {print s}' |
Scripting: variabili, condizioni, cicli, funzioni
| Attività | CMD (Prompt dei comandi) | PowerShell | Bash (Linux/macOS) |
|---|---|---|---|
| Impostare una variabile # bash: niente spazi attorno a = (name = Ada esegue un comando chiamato name). | set name=Ada | $name = 'Ada' | name=Ada |
| Usare una variabile in una stringa # | echo Hello %name% | "Hello $name" | echo "Hello $name" |
| Aritmetica # CMD e bash fanno solo calcoli con numeri interi; PowerShell usa i numeri .NET. | set /a n=5*3 | $n = 5 * 3 | n=$((5 * 3)) |
| Leggere l'input dell'utente # | set /p name=Name: | $name = Read-Host 'Name' | read -rp 'Name: ' name |
| Argomenti dello script # Nei file .bat %~1 rimuove le virgolette esterne. Un blocco param() dà agli script PowerShell parametri con nome e tipo. | %1 %2 … %* | $args[0] or param($Path) | $1 $2 … "$@" |
| If / else su una stringa # Gli operatori di confronto di PowerShell sono parole: -eq -ne -gt -lt -like -match. = e > sono assegnazione e reindirizzamento. | 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 |
| Confrontare numeri # 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 un file esiste # | if exist file.txt echo yes | if (Test-Path file.txt) { 'yes' } | if [ -f file.txt ]; then echo yes; fi |
| Codice di uscita dell'ultimo programma # In PowerShell, $? è $true/$false per l'ultimo comando; $LASTEXITCODE è il codice numerico dell'ultimo programma nativo. | echo %ERRORLEVEL% | $LASTEXITCODE | echo $? |
| Eseguire il comando successivo solo in caso di successo / errore # Gli operatori di concatenazione && e || sono arrivati in PowerShell 7.0; Windows PowerShell 5.1 li rifiuta. | build && deploy
build || echo failed | build && deploy (PowerShell 7+)
build; if ($?) { deploy } (5.1) | build && deploy
build || echo failed |
| Ciclo su un elenco # | 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 |
| Ciclo da 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 |
| Ciclo sulle righe di un file # | 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 |
| Ciclo while # CMD non ha while; in un file .bat usa goto con un'etichetta. | :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 |
| Definire e chiamare una funzione # Le funzioni PowerShell si chiamano come comandi: Greet Ada, non 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 |
| Salvare l'output di un comando in una variabile # | for /f "delims=" %i in ('hostname') do set h=%i | $h = hostname | h=$(hostname) |
| Scartare l'output # | command >nul 2>&1 | command *> $null | command >/dev/null 2>&1 |
| Commento # | rem comment
:: comment | # comment
<# block #> | # comment |
| File di script e come eseguirlo # PowerShell non esegue script dalla cartella corrente senza .\ e potrebbe bloccarli del tutto: vedi i criteri di esecuzione più sotto. | script.bat | .\script.ps1 | chmod +x script.sh && ./script.sh |
Insidie degli alias di PowerShell: ls, curl, wget, sc, where
PowerShell include alias che sembrano comandi Unix o CMD ma eseguono cmdlet con parametri diversi. Quali esistano dipende dall'edizione e dal sistema operativo. Get-Alias name mostra a cosa punta un nome nella tua sessione.
| Digiti | Windows PowerShell 5.1 | PowerShell 7 su Windows | PowerShell 7 su Linux/macOS |
|---|---|---|---|
curlNella 5.1 digita curl.exe per usare il vero curl. I suoi flag (-X, -H, -d) non significano nulla per Invoke-WebRequest. | Invoke-WebRequest | non è un alias: esegue curl.exe | curl nativo |
wgetUsa Invoke-WebRequest url -OutFile nome, oppure curl.exe -LO url. | Invoke-WebRequest | non è un alias (wget non è presente su Windows per impostazione predefinita) | wget nativo, se installato |
ls, dirFlag come ls -la non funzionano su Windows: usa 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 non è PowerShell valido: usa Remove-Item -Recurse -Force. | Copy-Item, Move-Item, Remove-Item | stessi cmdlet | comandi nativi |
ps, kill | Get-Process, Stop-Process | stessi cmdlet | comandi nativi |
sort, tee, diffIn PowerShell su Windows, diff a b confronta oggetti, non le righe di due file. | Sort-Object, Tee-Object, Compare-Object | stessi cmdlet | comandi nativi |
scNella 5.1, sc query scrive un file chiamato query. Usa sc.exe. | Set-Content | non è un alias: esegue sc.exe | n/d |
whereUsa where.exe per trovare un programma, oppure Get-Command. | Where-Object | Where-Object | Where-Object |
echoecho -n non elimina il ritorno a capo; usa Write-Host -NoNewline. | Write-Output | Write-Output | Write-Output |
man | help | help | man nativo |
Virgolette ed escape
La maggior parte dei bug del tipo “funziona in una shell, non in un'altra” dipende dalle virgolette. Il carattere di escape è diverso in ogni shell.
| Cosa | CMD | PowerShell | Bash |
|---|---|---|---|
| Stringa letterale (senza espansione) | Nessuna virgoletta letterale: %VAR% viene espansa anche dentro "…" | 'Cost: $5' | 'Cost: $5' |
| Stringa con variabili | "Hello %name%" | "Hello $name, it is $(Get-Date -Format t)" | "Hello $name, it is $(date +%R)" |
| Carattere di escape | ^ (es. ^& ^| ^>) | ` backtick (es. `n a capo, `t tabulazione, `$ $ letterale) | \ barra rovesciata |
| Virgolette dentro una stringa tra virgolette | "" dentro "…" per molti programmi; dipende dal programma | 'It''s' or "Say `"hi`"" | 'It'\''s' or "Say \"hi\"" |
| Continuazione di riga | ^ a fine riga | ` a fine riga (oppure termina la riga con | ) | \ a fine riga |
| % o $ letterale in uno script | %% in un file .bat | '$' tra virgolette singole oppure `$ | '$' tra virgolette singole oppure \$ |
| Passare argomenti intatti a un programma nativo | (non necessario) | --% impedisce a PowerShell di analizzare il resto della riga | (non necessario) |
Il passaggio delle virgolette ai programmi nativi (curl.exe, git, node) è cambiato in PowerShell 7.3: gli argomenti con virgolette doppie al loro interno ora vengono passati così come sono scritti, comportamento controllato da $PSNativeCommandArgumentPassing. In Windows PowerShell 5.1 lo stesso corpo JSON spesso richiede un doppio escape delle virgolette interne, ed è per questo che molti passano a Invoke-RestMethod con ConvertTo-Json.
Criteri di esecuzione: “l'esecuzione di script è disabilitata nel sistema”
PowerShell si rifiuta di eseguire file .ps1 quando il criterio di esecuzione è Restricted, che è di fatto il valore predefinito di Windows PowerShell nelle edizioni client di Windows (Windows 10 e 11). Windows Server usa per impostazione predefinita RemoteSigned: gli script locali vengono eseguiti, quelli scaricati devono essere firmati o sbloccati. Su Linux e macOS il criterio è Unrestricted e non può essere modificato.
Get-ExecutionPolicy -Listmostra il criterio per ogni ambito; vince l'ambito definito più specifico (i Criteri di gruppo prevalgono su tutto).Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUserconsente di eseguire i tuoi script senza diritti di amministratore.Unblock-File .\script.ps1rimuove il contrassegno “scaricato da Internet” da uno script di cui ti fidi.pwsh -ExecutionPolicy Bypass -File script.ps1(opowershellper la 5.1) applica un criterio a una sola sessione.
Il criterio di esecuzione è una sicura contro l'esecuzione accidentale di script, non un confine di sicurezza: chiunque può incollare il contenuto dello script nella console.
Windows PowerShell 5.1 e PowerShell 7 a confronto
- Due programmi:
powershell.exeè Windows PowerShell 5.1, integrato in Windows e non più aggiornato con nuove funzionalità.pwshè PowerShell 7, da installare a parte, multipiattaforma; i due possono convivere. - Operatori aggiunti nella 7.0:
&&e||tra comandi, l'operatore ternario$a ? 'yes' : 'no'e gli operatori di null-coalescing??/??=. - Codifica dei file: nella 5.1
>eOut-Filescrivono in UTF-16 LE, eSet-Contentusa la code page ANSI. PowerShell 7 scrive ovunque in UTF-8 senza BOM, che è ciò che si aspettano Git, gli strumenti Linux e la maggior parte degli editor. - Alias: la 7 ha eliminato
curl,wgetescsu Windows, e su Linux/macOS lascials,cp,rm,cat,pse altri ai comandi nativi (tabella sopra). - Moduli mancanti: i cmdlet solo per Windows come
Get-NetIPAddress,Test-NetConnectioneResolve-DnsNamefunzionano in PowerShell 7 su Windows ma non esistono su Linux o macOS.
Usare bash su Windows: WSL
Il Sottosistema Windows per Linux esegue una vera distribuzione Linux accanto a Windows, quindi ogni comando bash nella colonna di destra funziona così com'è scritto. wsl --install da un prompt con privilegi elevati lo installa con Ubuntu per impostazione predefinita (Windows 10 versione 2004 e successive, e Windows 11); wsl -l -v elenca le distribuzioni installate.
- Esegui un singolo comando Linux da CMD o PowerShell:
wsl ls -la, oppure usa una pipe tra i due:dir | wsl grep txt. - Le unità Windows compaiono in Linux sotto
/mnt/c; i file Linux sono raggiungibili da Esplora file in\\wsl.localhost\Ubuntu(build meno recenti:\\wsl$\Ubuntu). - Tieni i progetti nel file system Linux (~/), non in /mnt/c: l'accesso ai file attraverso il confine è molto più lento.
Per approfondire il lato Linux, consulta la guida rapida ai comandi Linux.
Hai trovato un problema o qualcosa che potrebbe andare meglio? Leggiamo ogni messaggio e sistemiamo le cose in fretta.
Questa tabella CMD vs PowerShell vs Bash mostra la stessa operazione nel Prompt dei comandi di Windows, in PowerShell e in bash sulla stessa riga: elencare e copiare file, cercare testo nei file (l'equivalente PowerShell di grep è Select-String), variabili d'ambiente, processi, rete, servizi, lettura e scrittura del contenuto dei file e scripting con variabili, condizioni, cicli e funzioni. Cerca un comando di una qualsiasi delle tre shell e ottieni i suoi equivalenti, ciascuno con un pulsante per copiarlo.
La guida copre anche ciò che di solito va storto passando da una shell all'altra: alias di PowerShell che sembrano comandi Unix ma non lo sono (curl e wget in Windows PowerShell 5.1, ls e rm ovunque su Windows), virgolette e caratteri di escape diversi, l'errore della execution policy che blocca gli script .ps1 e le differenze tra Windows PowerShell 5.1 e PowerShell 7. I comandi PowerShell funzionano in entrambe le versioni salvo diversa indicazione in una nota; quando un equivalente CMD non esiste, la tabella lo dice invece di inventarne uno.
Come si usa
- Cerca il comando che conosci, in qualsiasi shell (ad esempio “grep”, “findstr” o “Select-String”), oppure l'operazione (“terminare un processo”, “variabile d'ambiente”).
- Leggi la riga per trovare l'equivalente nelle altre due shell e fai clic su Copia accanto a quello che ti serve.
- Controlla la nota sotto il nome dell'operazione: segnala le differenze di versione (PowerShell 5.1 e 7) e i cmdlet solo per Windows.
- Scorri fino alle sezioni su alias, virgolette ed execution policy se un comando si comporta diversamente da come ti aspettavi.
- Usa Stampa / Salva come PDF per averne una copia sulla scrivania; la pagina funziona anche su telefono, dove ogni riga diventa una scheda.
Domande frequenti
Qual è l'equivalente PowerShell di grep?
Select-String. Cerca in un file con Select-String -Path app.log -Pattern error, oppure filtra l'output di un comando con ipconfig | Select-String IPv4. Per impostazione predefinita non distingue tra maiuscole e minuscole (aggiungi -CaseSensitive), usa le espressioni regolari .NET e -NotMatch equivale a grep -v. Per le ricerche ricorsive passa Get-ChildItem -Recurse -Filter *.log a Select-String tramite pipe. Il suo alias breve è sls.
Perché curl si comporta in modo strano in PowerShell?
In Windows PowerShell 5.1, curl e wget sono alias di Invoke-WebRequest, quindi opzioni di curl come -X, -H e -d vengono rifiutate o significano altro. Digita curl.exe per eseguire il vero curl incluso in Windows 10 1803 e versioni successive. PowerShell 7 ha rimosso quegli alias, quindi lì curl esegue curl.exe. Su Linux e macOS, curl non è mai stato un alias.
PowerShell è meglio di CMD?
Per qualsiasi cosa che vada oltre l'avvio di un programma o un breve file batch, sì. PowerShell passa tramite pipe oggetti strutturati invece di testo, quindi filtri e ordini per nome di proprietà (Where-Object, Sort-Object) invece di analizzare colonne, e ha vere funzioni, gestione degli errori, supporto per JSON e CSV e accesso remoto. CMD va ancora bene per i vecchi file .bat e alcuni programmi di installazione, e ogni strumento CMD (ipconfig, robocopy, netstat) si può eseguire anche da PowerShell.
Come si risolve “l'esecuzione di script è disabilitata nel sistema”?
È la execution policy, che per impostazione predefinita è Restricted nelle edizioni client di Windows 10 e 11. Esegui Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser in PowerShell (non servono privilegi di amministratore). A quel punto i tuoi script vengono eseguiti, mentre quelli scaricati da internet devono essere firmati o sbloccati con Unblock-File. Get-ExecutionPolicy -List mostra cosa è impostato e dove; un'impostazione di Criteri di gruppo prevale su qualsiasi cosa imposti tu.
Posso eseguire comandi bash su Windows?
Sì, con il Sottosistema Windows per Linux (WSL). Esegui wsl --install da un prompt con privilegi elevati (Windows 10 versione 2004 o successiva, oppure Windows 11) per installare Ubuntu, poi aprilo dal menu Start o esegui singoli comandi da CMD o PowerShell con wsl seguito dal comando, ad esempio wsl grep -rn TODO. Git for Windows include anche Git Bash, una bash più leggera con i comuni strumenti Unix.
Che differenza c'è tra Windows PowerShell e PowerShell 7?
Windows PowerShell 5.1 (powershell.exe) è integrato in Windows e riceve solo correzioni. PowerShell 7 (pwsh) è la versione attuale e multipiattaforma, che gira su Windows, Linux e macOS e si installa a parte; le due possono essere installate insieme. La versione 7 aggiunge && e || tra i comandi, l'operatore ternario e ??, scrive file UTF-8 per impostazione predefinita ed elimina alcuni alias fuorvianti come curl e wget.
Oggetti contro testo: l'idea che ti fa capire PowerShell
In CMD e bash una pipe trasporta testo. Per trovare in bash il processo che usa più memoria devi estrarre la colonna giusta dall'output di ps con sort -k o awk, e il comando si rompe se il layout delle colonne cambia. In PowerShell la pipe trasporta oggetti con proprietà denominate, quindi la stessa operazione è Get-Process | Sort-Object WS -Descending | Select-Object -First 1. Non si analizza nulla, e i nomi delle proprietà sono gli stessi su ogni macchina.
La conseguenza pratica è un modo diverso di esplorare. In bash leggi una pagina man per conoscere il formato dell'output; in PowerShell passi qualsiasi comando a Get-Member per vedere quali proprietà e metodi hanno i suoi oggetti, poi filtri con Where-Object e scegli i campi con Select-Object. Solo quando l'output arriva allo schermo o a un file PowerShell lo trasforma in testo.
I programmi nativi come ipconfig, git o curl.exe producono comunque testo in PowerShell, quindi Select-String e -match funzionano su di essi come farebbe grep. Il loro codice di uscita si trova in $LASTEXITCODE, non in $?.
Tradurre uno script tra le tre shell
La traduzione riga per riga funziona per gli script semplici, ma alcune differenze fregano quasi tutti:
• Operatori di confronto: CMD usa == per le stringhe ed EQU, GTR, LSS per i numeri; PowerShell usa -eq, -gt, -lt, -like e -match (un > da solo è un reindirizzamento); bash usa = dentro [ ] per le stringhe e -gt o (( )) per i numeri.
• Variabili: %name% in CMD (e !name! nei cicli dopo setlocal EnableDelayedExpansion), $name in PowerShell, $name in bash senza spazi attorno a = nell'assegnazione.
• Nei file .bat i cicli raddoppiano il segno di percentuale: for %%f in (*.txt) dentro un file, for %f al prompt.
• Percorsi: su Windows PowerShell accetta sia / sia \; bash su Linux richiede /. Le variabili d'ambiente non distinguono maiuscole e minuscole su Windows, mentre le distinguono su Linux.
• Errori: CMD prosegue dopo un errore a meno che tu non controlli %ERRORLEVEL%; bash prosegue a meno di set -e; PowerShell prosegue dopo gli errori non terminanti a meno di $ErrorActionPreference = 'Stop'.
Quando uno script deve girare su Windows e Linux, PowerShell 7 o bash sotto WSL evitano di dover mantenere due copie.
Strumenti gratuiti correlati
- Guida rapida ai comandi Linux — Comandi Linux per attività, da file e permessi a rete, systemd ed elaborazione del testo. Ogni voce ha opzioni, esempi da copiare e note per macOS.
- Scorciatoie da tastiera di Windows — Tutte le scorciatoie di Windows 11 in un unico elenco consultabile e stampabile: tasto Win, Snap, desktop, screenshot, Esplora file.
- Scorciatoie da tastiera Mac — Tutte le scorciatoie di macOS con i simboli ⌘ ⌥ ⌃ ⇧ spiegati: screenshot, affiancamento delle finestre, Finder, Safari e caratteri speciali.
- Da curl a codice — Incolla un comando curl, anche da "Copia come cURL" di Chrome, e ottieni la stessa richiesta in Python, JavaScript, Node, Go, PHP, Ruby, Java, C#, wget o HTTPie.
- Guida rapida Git — Comandi Git organizzati per ciò che vuoi fare: annullare l'ultimo commit, rinominare un branch, eliminare un branch remoto. I moderni switch/restore con gli equivalenti classici e badge di pericolo.