ARGOMENTO about_Foreach DESCRIZIONE BREVE Descrive un comando del linguaggio che è possibile utilizzare per attraversare tutti gli elementi in una raccolta di elementi. DESCRIZIONE DETTAGLIATA L'istruzione Foreach, nota anche come ciclo Foreach, è un costrutto del linguaggio che consente di passare attraverso una serie di valori in una raccolta di elementi. Il tipo di insieme più semplice e comune da attraversare è la matrice. In un ciclo Foreach, vengono in genere eseguiti uno o più comandi su ogni elemento di una matrice. Sintassi Di seguito viene illustrata la sintassi dell'istruzione Foreach: foreach ($<elemento> in $<raccolta>){<elenco istruzioni>} Istruzione Foreach esterna a una pipeline di comandi La parte dell'istruzione Foreach racchiusa tra parentesi rappresenta una variabile e una raccolta da scorrere. In Windows PowerShell, la variabile ($<elemento>) viene creata automaticamente al momento dell'esecuzione del ciclo Foreach. Prima di ogni iterazione del ciclo, la variabile viene impostata su un valore dell'insieme. Il blocco {<elenco istruzioni>} che segue l'istruzione Foreach contiene un set di comandi da eseguire su ogni elemento di una raccolta. Esempi Ad esempio, il ciclo Foreach riportato di seguito consente di visualizzare i valori della matrice $letterArray. $letterArray = "a","b","c","d" foreach ($letter in $letterArray) { Write-Host $letter } In questo esempio, la matrice $letterArray viene creata e inizializzata con i valori stringa "a", "b", "c" e "d". Alla prima esecuzione dell'istruzione Foreach, la variabile $letter viene impostata su un valore uguale al primo elemento della matrice $letterArray ("a"). Quindi, viene utilizzato il cmdlet Write-Host per visualizzare la lettera a. Al ciclo successivo, la variabile $letter viene impostata su "b" e così via. Dopo la visualizzazione della lettera d, il ciclo Foreach viene chiuso. Si noti che l'intera istruzione Foreach deve trovarsi su una singola riga per poter essere eseguita come comando al prompt dei comandi di Windows PowerShell. Al contrario, non è necessario che l'intera istruzione Foreach si trovi su una singola riga se il comando viene inserito in un file di script con estensione ps1. Le istruzioni Foreach possono essere utilizzate anche con i cmdlet che restituiscono una raccolta di elementi. Nell'esempio seguente l'istruzione Foreach scorre l'elenco degli elementi restituiti dal cmdlet Get-ChildItem. foreach ($file in Get-ChildItem) { Write-Host $file } L'esempio può essere perfezionato mediante un'istruzione If che limiti il risultato restituito. Nell'esempio seguente l'istruzione Foreach esegue la stessa operazione ciclica dell'esempio precedente, ma con l'aggiunta di un'istruzione If che limita il risultato ai file di dimensioni maggiori di 100 kilobyte (KB): foreach ($file in Get-ChildItem) { if ($file.length -gt 100k) { Write-Host $file } } Nel ciclo Foreach di questo esempio viene utilizzata una proprietà della variabile $file per eseguire un'operazione di confronto ($file.length -gt 100k). Nella variabile $file sono contenute tutte le proprietà dell'oggetto restituito dal cmdlet Get- ChildItem. È pertanto possibile ottenere più di un semplice nome file. Nell'esempio seguente, vengono restituite la lunghezza e l'ora dell'ultimo accesso nell'elenco di istruzioni: foreach ($file in Get-ChildItem) { if ($file.length -gt 100k) { Write-Host $file Write-Host $file.length Write-Host $file.lastaccesstime } } In questo esempio, non ci si limita all'esecuzione di un singolo comando in un elenco di istruzioni. È inoltre possibile utilizzare una variabile esterna a un ciclo Foreach e incrementare la variabile all'interno del ciclo stesso. Nell'esempio seguente vengono contati i file di dimensioni maggiori a 100 KB: $i = 0 foreach ($file in Get-ChildItem) { if ($file.length -gt 100k) { Write-Host $file "file size:" ($file.length / 1024).ToString("F0") KB $i = $i + 1 } } if ($i -ne 0) { Write-Host Write-Host $i " file con dimensioni maggiori di 100 KB nella directory corrente".} else { Write-Host "Nessun file con dimensioni maggiori di 100 KB nella directory corrente". } Nell'esempio precedente, la variabile $i viene impostata su 0 all'esterno del ciclo e viene incrementata all'interno del ciclo per ciascun file individuato con dimensioni maggiori di 100 KB. Alla chiusura del ciclo, l'istruzione If valuta il valore di $i per visualizzare il conteggio di tutti i file con dimensioni maggiori di 100 KB. In alternativa, viene visualizzato un messaggio che segnala l'impossibilità di trovare file con dimensioni maggiori di 100 KB. L'esempio precedente mostra anche come formattare il risultato della lunghezza dei file: ($file.length / 1024).ToString("F0") Il valore viene diviso per 1.024 in modo da visualizzare il risultato in kilobyte anziché in byte. Il valore risultante viene poi formattato mediante l'identificatore di formato a virgola fissa per rimuovere i valori decimali dal risultato. Con la cifra 0 l'identificatore di formato non visualizza alcuna cifra decimale. Istruzione Foreach interna a una pipeline di comandi Se Foreach è presente in una pipeline di comandi, Windows PowerShell utilizza l'alias foreach che chiama il comando ForEach-Object. Se si include l'alias foreach in una pipeline di comandi, non utilizzare la sintassi ($<elemento> in $<insieme>) come invece avviene con l'istruzione Foreach, in quanto tali informazioni vengono fornite dal primo comando della pipeline. La sintassi dell'alias foreach se utilizzato in una pipeline di comandi è la seguente: <comando> | foreach {<blocco_comandi>} Ad esempio, il ciclo Foreach nella pipeline di comandi seguente consente di visualizzare i processi il cui working set (utilizzo della memoria) è maggiore di 20 megabyte (MB). Windows PowerShell trasferisce lungo la pipeline l'output del comando Get-Process all'alias foreach. La variabile $_.WS, che si trova all'interno del blocco di comandi dell'alias foreach, contiene il valore della proprietà WS (working set) passato dal cmdlet Get-Process. La parte $_ della dichiarazione è una variabile automatica WSH mentre la parte WS è una proprietà. L'istruzione If utilizza un'istruzione condizionale per stabilire se il working set è maggiore di 20 MB (20.000.000 byte). In tal caso, vengono visualizzati il nome del processo archiviato nella variabile $_.name e le dimensioni in megabyte del working set. Se nessun working set è maggiore di 20 MB, non viene visualizzato nulla. Write-Host "Processi con working set maggiori di 20 MB" Get-Process | foreach { if ($_.WS -gt 20m) { Write-Host $_.name ": " ($_.WS/1m).ToString("F0") MB -Separator "" } } L'alias foreach supporta anche i blocchi di comandi iniziale, intermedio e finale. I blocchi di comandi iniziale e finale vengono eseguiti una sola volta mentre il blocco di comandi intermedio viene eseguito ogni volta che il ciclo Foreach attraversa una raccolta o una matrice. La sintassi dell'alias foreach se utilizzato in una pipeline di comandi con blocchi di comandi iniziale, intermedio e finale è la seguente: <comando> | foreach {<blocco_comandi_iniziale>}{<blocco_comandi_ intermedio>}{<blocco_coman di_finale>} Nell'esempio seguente viene illustrato l'utilizzo dei blocchi di comandi iniziale, intermedio e finale. Get-ChildItem | foreach { $fileCount = $directoryCount = 0}{ if ($_.PsIsContainer) {$directoryCount++} else {$fileCount++}}{ "directory $directoryCount e file $fileCount"} Il blocco iniziale crea e inizializza due variabili su 0: {$fileCount = $directoryCount = 0} Il blocco intermedio valuta se ciascun elemento restituito da Get- ChildItem è una directory o un file: {if ($_.PsIsContainer) {$directoryCount++} else {$fileCount++}} Se l'elemento restituito è una directory, la variabile $directoryCount viene incrementata di 1. Se l'elemento non è una directory, la variabile $fileCount viene incrementata di 1. Il blocco finale viene eseguito dopo che il blocco intermedio ha completato l'operazione ciclica, quindi vengono restituiti i risultati dell'operazione: {"directory $directoryCount e file $fileCount"} L'esempio precedente può essere riscritto come segue, utilizzando la struttura dei blocchi di comandi iniziale, intermedio e finale nonché l'operatore pipeline, per individuare i file con dimensioni maggiori di 100 KB: Get-ChildItem | foreach{ $i = 0}{ if ($_.length -gt 100k) { Write-Host $_.name "file size:" ($_.length / 1024).ToString("F0") KB $i++ } }{ if ($i -ne 0) { Write-Host Write-Host "$i file con dimensioni maggiori di 100 KB nella directory corrente". } else { Write-Host "Nessun file con dimensioni maggiori di 100 KB nella directory corrente".} } VEDERE ANCHE about_Automatic_Variables about_If Foreach-Object