È uscito il Corso Java Completo
Torna al blog

Cos'è PowerShell e perché è diverso da tutto il resto

Come funziona PowerShell, perché lavora con oggetti invece che con testo, i cmdlet essenziali e le differenze pratiche rispetto a CMD e Bash.

Edoardo Midali

Edoardo Midali

Developer · Content Creator

7 min di lettura

Chi arriva a PowerShell dal mondo Unix di solito lo giudica male nei primi dieci minuti: i comandi sono lunghi, la sintassi è verbosa e sembra tutto più macchinoso. Poi capisce la cosa che lo rende diverso da ogni altra shell — non lavora con testo — e la verbosità comincia ad avere senso. In questo articolo trovi come funziona, i comandi che servono davvero e cosa cambia rispetto a Bash.

Cos'è

PowerShell è la shell e il linguaggio di scripting di Microsoft, e la sua caratteristica distintiva è che i comandi si scambiano oggetti strutturati invece che righe di testo.

Sembra un dettaglio tecnico. È invece la differenza che determina come si scrive tutto il resto.

Due precisazioni utili prima di andare avanti:

PowerShell non è CMD. Il vecchio prompt dei comandi di Windows è un'altra cosa, molto più limitata. Se conosci solo quello, il contesto è in CMD, terminale e PowerShell.

PowerShell funziona anche su Linux e macOS. Dalla versione 7 (quella attuale, chiamata semplicemente PowerShell, mentre la 5.1 preinstallata su Windows si chiama Windows PowerShell) è multipiattaforma e open source.

La differenza che cambia tutto: gli oggetti

In Bash, ogni comando produce testo e il comando successivo deve ritagliarlo per estrarre quello che gli serve. È il motivo per cui strumenti come grep, awk, sed e cut sono indispensabili: servono a interpretare testo.

Il classico "quali processi consumano più memoria" su Unix richiede di ritagliare colonne:

ps aux | sort -nrk 4 | head -5 | awk '{print $11, $4}'

Funziona, ma dipende dalla posizione delle colonne: cambia il formato dell'output e lo script si rompe.

In PowerShell:

Get-Process | Sort-Object WorkingSet -Descending | Select-Object -First 5 Name, WorkingSet

Non c'è nessun ritaglio di testo. Get-Process restituisce oggetti processo con proprietà vere, e i comandi successivi lavorano su quelle proprietà per nome. Se cambia la formattazione a schermo, lo script continua a funzionare, perché non dipendeva dalla formattazione.

Questo è il vantaggio strutturale di PowerShell, ed è anche la ragione della verbosità: i nomi lunghi sono il prezzo di un modello in cui non devi indovinare in quale colonna stia il dato.

La sintassi dei comandi

I comandi si chiamano cmdlet e seguono sempre lo schema Verbo-Sostantivo:

Get-Process
Stop-Service
New-Item
Remove-Item
Set-Location

La convenzione è rigida, ed è il motivo per cui PowerShell si indovina. Se sai che esiste Get-Service, sai che esistono Start-Service, Stop-Service e Restart-Service senza doverlo cercare.

Per scoprire cosa esiste:

Get-Command *service*        # cerca cmdlet
Get-Help Get-Process -Full   # documentazione completa
Get-Help Get-Process -Examples
Get-Process | Get-Member     # QUALI PROPRIETÀ ha l'oggetto

Get-Member è il comando più utile da imparare per primo. Ti dice esattamente quali proprietà e metodi ha quello che stai ricevendo, quindi cosa puoi usare nel comando successivo. Senza, si procede a tentativi.

Gli alias rendono l'uso interattivo più sopportabile:

ls      # Get-ChildItem
cd      # Set-Location
cat     # Get-Content
rm      # Remove-Item
ps      # Get-Process

Attenzione però: negli script conviene scrivere i nomi completi. Gli alias possono cambiare o non esistere su un'altra macchina, e chi legge lo script un anno dopo ti ringrazia.

I comandi che userai

Sui file:

Get-ChildItem -Recurse -Filter *.log      # elenca ricorsivamente
Get-Content log.txt -Tail 20              # ultime 20 righe
Get-Content log.txt -Wait                 # segui in tempo reale
Copy-Item origine.txt destinazione.txt
Remove-Item vecchio.txt
New-Item -ItemType Directory nuova-cartella
Test-Path C:\percorso                     # esiste?

Filtrare e ordinare — lo schema che si ripete ovunque:

Get-ChildItem | Where-Object { $_.Length -gt 1MB }
Get-Process | Where-Object { $_.CPU -gt 100 }
Get-ChildItem | Sort-Object LastWriteTime -Descending
Get-Process | Select-Object Name, CPU -First 10

$_ rappresenta l'oggetto corrente nella pipeline. È l'equivalente concettuale della riga corrente in Bash, ma è un oggetto completo con tutte le sue proprietà.

Servizi e processi:

Get-Service | Where-Object Status -eq Running
Restart-Service -Name Spooler
Stop-Process -Name blocco-notes -Force

Rete:

Test-NetConnection google.com -Port 443
Get-NetIPAddress
Invoke-WebRequest https://api.esempio.it/dati

Dove il modello a oggetti si nota davvero

Esportare in CSV senza scrivere una riga di formattazione:

Get-Process | Select-Object Name, CPU, WorkingSet | Export-Csv processi.csv -NoTypeInformation

Leggere JSON come struttura navigabile, non come testo:

$dati = Get-Content config.json | ConvertFrom-Json
$dati.database.host

Questa è la cosa che in Bash richiede uno strumento esterno e che qui è integrata. Per chi lavora con API e file di configurazione, è il vantaggio più concreto nell'uso quotidiano.

Uno script vero

param(
    [Parameter(Mandatory=$true)]
    [string]$Cartella,
    [int]$GiorniDaTenere = 30
)

$ErrorActionPreference = "Stop"

if (-not (Test-Path $Cartella)) {
    Write-Error "La cartella $Cartella non esiste"
    exit 1
}

$limite = (Get-Date).AddDays(-$GiorniDaTenere)

$daEliminare = Get-ChildItem -Path $Cartella -Filter *.log |
    Where-Object { $_.LastWriteTime -lt $limite }

Write-Host "Trovati $($daEliminare.Count) file da eliminare"

foreach ($file in $daEliminare) {
    Write-Host "Elimino $($file.Name)"
    Remove-Item $file.FullName
}

Due righe meritano attenzione.

$ErrorActionPreference = "Stop" è l'equivalente di set -e in Bash: senza, molti errori non interrompono lo script, che prosegue in uno stato incoerente. Va messa in cima a ogni script serio.

param() con Mandatory dà validazione automatica dei parametri: se manca, PowerShell lo chiede invece di fallire a metà esecuzione.

Prima di eseguire qualcosa di distruttivo, la rete di sicurezza integrata:

Remove-Item vecchio.txt -WhatIf     # mostra cosa farebbe, senza farlo
Remove-Item vecchio.txt -Confirm    # chiedi conferma

-WhatIf non ha equivalente diretto in Bash ed è una delle cose migliori di PowerShell: provi il comando distruttivo a vuoto e vedi l'elenco esatto di cosa toccherebbe.

Errori comuni

Gli script non partono per la politica di esecuzione. Errore classico alla prima volta. Windows blocca l'esecuzione degli script per impostazione predefinita:

Get-ExecutionPolicy
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

RemoteSigned è il compromesso sensato: i tuoi script girano, quelli scaricati devono essere firmati. Evita Unrestricted: quella protezione esiste per una ragione.

Confondere -eq con =. In PowerShell = assegna, e i confronti si fanno con -eq, -ne, -gt, -lt, -like. Chi arriva da altri linguaggi ci inciampa sempre.

Usare gli alias negli script. Funzionano da te, poi non altrove.

Dimenticare le parentesi in $_.Proprietà dentro una stringa. Serve $($file.Name), non $file.Name: senza le parentesi, la stringa contiene la rappresentazione dell'oggetto seguita da .Name letterale.

Aspettarsi che curl sia curl. In Windows PowerShell è un alias di Invoke-WebRequest, che ha una sintassi completamente diversa. Fonte di confusione ricorrente quando si copiano comandi trovati online.

PowerShell o Bash?

PowerShellBash
Modello dei datiOggettiTesto
Su WindowsNativoTramite WSL
Su Linux/serverDa installareOvunque
Gestione di WindowsInsuperabileNo
ConcisioneVerbosoConciso
JSON e APIIntegratiStrumenti esterni

Non è una scelta da fare una volta per tutte. La linea di demarcazione pratica:

PowerShell per amministrare Windows — Active Directory, servizi, registro, Exchange, Azure. Su quel terreno non ha rivali.

Bash per i server Linux e per gli script che devono girare ovunque. È preinstallata su ogni macchina Linux che incontrerai, e questo pesa più di ogni vantaggio sintattico — vedi Bash scripting.

Se sviluppi su Windows ma pubblichi su Linux, la configurazione più sensata è entrambe: PowerShell per la macchina, WSL per lavorare nello stesso ambiente della produzione.

In sintesi

PowerShell è una shell che scambia oggetti invece che testo, e da questa scelta discende tutto il resto: nomi verbosi ma prevedibili, nessun bisogno di ritagliare colonne, script che non si rompono quando cambia la formattazione.

Le tre cose da imparare per prime sono Get-Member per scoprire cosa hai tra le mani, la coppia Where-Object e Select-Object per filtrare, e -WhatIf per provare a vuoto i comandi distruttivi.

Negli script metti sempre $ErrorActionPreference = "Stop" e i nomi completi dei cmdlet.

È lo strumento giusto per amministrare Windows e per lavorare con JSON e API. Per i server Linux, Bash resta la scelta pragmatica, perché è già lì.