Elaborare Dati CSV con Import-Csv e Ciclo ForEach in PowerShell

Hai mai dovuto fare lo stesso compito più volte? Ad esempio, creare più utenti di Active Directory uno alla volta utilizzando l’interfaccia grafica? O cosa ne dici di accedere a un server per eliminare vecchi log da alcune cartelle selezionate? Se la tua risposta è , sappi che non sei solo. È ora di padroneggiare l’utilizzo di Import-Csv di PowerShell e del ciclo foreach.

Non c’è nulla di sbagliato nei compiti manuali; a volte è necessario. Ma quando si tratta di leggere e elaborare file CSV, il cmdlet di PowerShell Import-Csv e il ciclo ForEach possono essere di grande aiuto.

Il cmdlet Import-Csv di PowerShell è un ottimo modo per leggere dati da una fonte tabellare come un file CSV. Puoi utilizzare il ciclo ForEach per iterare su ogni riga dei dati CSV.

In questo articolo imparerai come utilizzare questa potente combinazione per automatizzare compiti di massa, noiosi e ripetitivi.

Se sei nuovo nel cmdlet Import-Csv e nel ciclo ForEach, o se desideri un ripasso di ciò che già sai, puoi visitare questi link per saperne di più.

Gestione dei file CSV in PowerShell con Import-Csv (ciclo foreach)

Back to Basics: Il ciclo foreach di PowerShell

Prerequisiti

In questo articolo sono presenti diversi esempi e demo. Per seguirmi, avrai bisogno di alcune cose.

  • A script editor such as Visual Studio Code, Atom, or Notepad++. Use whichever one you’re comfortable with.
  • Windows PowerShell 5.1 o PowerShell Core 6+
  • Accesso a Exchange Online (opzionale se si seguono gli esempi pratici relativi a Exchange Online).

Mettere in azione Import-Csv e il ciclo ForEach

Nelle sezioni seguenti sono presenti diversi esempi su come utilizzare il cmdlet Import-Csv e il ciclo ForEach che potresti incontrare in scenari reali. Sebbene questi esempi specifici per PowerShell di importazione CSV foreach siano specifici per ogni scopo, è fondamentale capire che il concetto e la tecnica utilizzati sono gli stessi.

Lettura e visualizzazione dei record da un file CSV

Forse l’utilizzo più basilare di Import-Csv e del ciclo ForEach è leggere i record da un file e visualizzarli nella console. L’anatomia di un file CSV è simile a quella di un database. Ha intestazioni di colonna e ogni riga viene considerata come un record.

Ad esempio, di seguito è riportato il contenuto del file chiamato employee.csv, che consiste in tre colonne – EmployeeID, Name, e Birthday, e quattro record.

CSV containing employee records

Il codice di seguito importa il contenuto del file employee.csv e poi invia i dati importati al cmdlet ForEach-Object. Successivamente, ForEach-Object passerà attraverso ogni record nel CSV importato per visualizzare i valori concatenati nella console. Copia il codice di seguito e salvato come list-employee.ps1.

Nota: Il tipo di ciclo ForEach utilizzato nell’esempio qui di seguito è il cmdlet ForEach-Object. Fare riferimento alla sezione “Il cmdlet ForEach-Object” in questo articolo.

Import-Csv .\employee.csv | ForEach-Object {
    Write-Host "$($_.Name), whose Employee ID is $($_.EmployeeID), was born on $($_.Birthday)."
}

Una volta che lo script è salvato, eseguirlo chiamando il suo nome file in PowerShell. Quando lo script viene eseguito, dovresti vedere un output simile allo screenshot qui sotto.

Imported CSV records displayed in the console

Ricerca e visualizzazione dei record da un file CSV

Nell’esempio precedente, hai imparato come leggere e visualizzare tutti i record da un file CSV. In questo esempio, verrà utilizzato lo stesso file CSV employee.csv, ma questa volta creerai una funzione PowerShell per cercare un EmployeeID nel CSV.

Il frammento di codice qui sotto è una funzione PowerShell chiamata Trova-Employee che ha un solo parametro. Il nome del parametro è EmployeeID e accetta un valore di ID dipendente da cercare nel CSV.

Prima che questa funzione possa essere utilizzata, deve essere importata nella sessione di PowerShell. Ci sono due modi per importare la funzione Trova-Employee nella memoria:

  1. Copiare e incollare il codice qui sotto in PowerShell.
  2. Salvare lo script come Trova-Employee.ps1 e importarlo utilizzando la tecnica del dot-sourcing.

Nota: Il tipo di ciclo ForEach utilizzato nell’esempio qui sotto è il ciclo ForEach Statement. Fare riferimento alla sezione “La dichiarazione foreach” in questo articolo.

Function Find-Employee {
    param (
        # Il parametro accetta l'ID dell'impiegato da cercare.
        [Parameter(Mandatory)]
        $EmployeeID
    )

    # Importa il contenuto del file employee.csv e memorizzalo nella variabile $employee_list.
    $employee_list = Import-Csv .\employee.csv

    # Esegui un ciclo su tutti i record nel CSV
    foreach ($employee in $employee_list) {

        # Verifica se l'ID dell'impiegato del record corrente è uguale al valore del parametro EmployeeID.
        if ($employee.EmployeeID -eq $EmployeeID) {

            # Se l'EmployeeID viene trovato, visualizza il record sulla console.
            Write-Host "$($employee.Name), whose Employee ID is $($employee.EmployeeID), was born on $($employee.Birthday)."
        }
    }
}

Una volta importato il codice della funzione nella sessione di PowerShell, chiamalo digitando il nome della funzione come segue.

Find-Employee

Quando la funzione viene eseguita senza utilizzare il parametro EmployeeID, verrà richiesto il valore di EmployeeID da cercare. Vedi l’esempio di output qui sotto.

Function to search a CSV file for a specific record

O, la funzione può essere eseguita specificando il valore del parametro EmployeeID durante l’esecuzione, come mostrato qui sotto.

Find-Employee -EmployeeID 'E-2023'

Ottenere l’utilizzo dello spazio su disco da più server

Un’attività comune tra gli amministratori di sistema è il monitoraggio dell’utilizzo dello spazio su disco di più server. Invece di accedere a ciascun server per controllare l’utilizzo dello spazio su disco, è possibile creare un elenco CSV contenente i nomi dei server, le lettere delle unità e le soglie. Quindi, utilizzando PowerShell, importare il file CSV e eseguire un ciclo su ciascuna riga per eseguire una query.

Per creare uno script che ottiene l’utilizzo dello spazio su disco da server remoti, prima crea una lista CSV con le seguenti intestazioni:

  • nome_server – questo è il nome del server da interrogare.
  • disco – questa è la lettera dell’unità di disco di cui verrà recuperato l’utilizzo dello spazio.
  • soglia – questo definisce la soglia in GB. Se lo spazio libero del disco è inferiore a questo valore, il rapporto mostrerà uno stato di avviso.

Nell’esempio sottostante sono elencati quattro record. Il tuo file CSV sarà diverso a seconda del numero di server o dischi da leggere.

servername,disk,threshold
au-dc01,c,120
au-mail01,c,100
au-mail01,d,6
au-file01,c,120

Una volta finalizzato il CSV, salva il file come servers.csv. Questo servirà come elenco di input che verrà importato dallo script PowerShell.

Per fornire un esempio di ottenere l’utilizzo dello spazio su disco, copia il codice sottostante nel tuo editor di script e salvalo come diskReport.ps1. Lo script deve essere salvato nella stessa posizione del percorso CSV.

$server_list = Import-Csv -Path .\servers.csv

foreach ($server in $server_list) {
    Get-WmiObject -Class Win32_logicaldisk -ComputerName ($server.servername) | `
        Where-Object { $_.DeviceID -match ($server.disk) } | `
        Select-Object `
    @{n = 'Server Name'; e = { $_.SystemName } }, `
    @{n = 'Disk Letter'; e = { $_.DeviceID } }, `
    @{n = 'Size (GB)'; e = { $_.Size / 1gb -as [int] } }, `
    @{n = 'Free (GB)'; e = { $_.FreeSpace / 1gb -as [int] } }, `
    @{n = 'Threshold (GB)'; e = { $server.Threshold } }, `
    @{n = 'Status'; e = {
            if (($_.FreeSpace / 1gb) -lt ($server.Threshold)) {
                return 'Warning'
            }
            else {
                return 'Normal'
            }
        }
    }
}

Lo script sopra esegue le seguenti azioni una volta eseguito.

  • Importa il file csv chiamato servers.csv e memorizzalo nella variabile $server_list.
  • Scorri l’elenco di server memorizzati nella variabile $server_list.
  • In ogni iterazione del ciclo foreach, la riga corrente è rappresentata dalla variabile $server.
  • Ottieni le informazioni sul disco dai server utilizzando il cmdlet Get-WmiObject.
  • Selezionare solo le proprietà rilevanti da visualizzare.
    Nome del server – Questo è il nome del sistema che viene interrogato.
    Lettera del disco – La lettera assegnata all’unità.
    Dimensione (GB) – La dimensione del disco in GB.
    Spazio libero (GB) – La dimensione dello spazio libero in GB.
    Soglia (GB) – La soglia definita in GB.
    Stato – Se il valore di Spazio libero (GB) è inferiore al valore di Soglia (GB), lo stato restituito è “Avviso”. In caso contrario, lo stato sarà “Normale”.

Avendo salvato il file di script diskReport.ps1, è ora pronto per essere eseguito chiamando il suo nome in PowerShell.

./diskReport.ps1

Una volta eseguito, la schermata sottostante mostra l’output dello script.

Disk space information gathered from multiple servers

L’output può anche essere esportato in CSV. L’esportazione in CSV è utile quando il rapporto deve essere condiviso perché il file CSV esportato può essere inviato per email o caricato su un file share o su un sito SharePoint. Assicurati di dare un’occhiata a Export-Csv: Il modo di PowerShell per trattare i file CSV come cittadini di prima classe se desideri ulteriori informazioni sull’esportazione in CSV.

Creazione di utenti multipli in Active Directory

A questo punto, avrai già un’idea chiara sull’utilizzo di Import-Csv e ForEach. Questo prossimo esempio va un po’ oltre aggiungendo i cmdlet New-ADUser e Get-ADUser al mix.

Supponiamo di aver ricevuto un file CSV new_employees.csv contenente l’elenco dei nuovi dipendenti dal dipartimento delle risorse umane. Ogni riga nel file CSV rappresenta un utente da inserire e ha le seguenti colonne: Nome, Cognome, Dipartimento, Stato, ID dipendente e Ufficio.

Il nome utente deve essere derivato dalla prima lettera del nome concatenata con il cognome dell’utente (ad esempio, bparr per l’utente Bob Parr).

CSV file containing new employees information for on-boarding

Dopo aver salvato il file CSV, lo script di seguito utilizza Import-Csv per leggere il file CSV new_employees.csv. Successivamente, itera attraverso ogni riga, passando i valori ai parametri appropriati di New-ADUser.

Import-Csv .\new_employees.csv | ForEach-Object {
    New-ADUser `
        -Name $($_.FirstName + " " + $_.LastName) `
        -GivenName $_.FirstName `
        -Surname $_.LastName `
        -Department $_.Department `
        -State $_.State `
        -EmployeeID $_.EmployeeID `
        -DisplayName $($_.FirstName + " " + $_.LastName) `
        -Office $_.Office `
        -UserPrincipalName $_.UserPrincipalName `
        -SamAccountName $_.SamAccountName `
        -AccountPassword $(ConvertTo-SecureString $_.Password -AsPlainText -Force) `
        -Enabled $True
}

Dopo aver eseguito lo script, i nuovi utenti dovrebbero già esistere in Active Directory. Tuttavia, è buona pratica confermare che gli account utente siano stati effettivamente creati.

Utilizzando lo stesso file CSV new_employees.csv come riferimento, lo script di seguito eseguirà l’importazione del CSV e un ciclo for each per ottenere gli oggetti ADUser corrispondenti a quelli nell’elenco.

Import-Csv .\new_employees.csv | ForEach-Object {
	Get-AdUser $_.SamAccountName
}

Aggiunta di un indirizzo email proxy alla casella di posta di Office 365

Nella gestione della casella di posta di Office 365, non è raro ricevere richieste di aggiunta di indirizzi proxy per più utenti. Comunemente, in questo tipo di richiesta, l’amministratore riceve un elenco di utenti e l’indirizzo email da aggiungere, simile all’esempio di CSV riportato di seguito.

The new_address.csv file contents

Nota: Prima di poter eseguire qualsiasi cmdlet di Exchange Online in PowerShell, devi prima accedere alla shell di Gestione di Exchange Online.

Utilizzando l’istruzione Import-Csv e il ciclo ForEach in uno script PowerShell, è possibile elaborare l’elenco in un’unica operazione. Lo script di seguito mostra come farlo.

Lo script di seguito importa i contenuti del file new_address.csv e li memorizza nella variabile $user_list. Quindi, utilizzando il metodo foreach(), PowerShell esegue un ciclo sull’intero elenco di utenti e utilizza i valori username e email di ogni record per aggiungere un nuovo indirizzo email a ciascuna casella di posta.

$user_list = Import-Csv .\new_address.csv

$user_list.foreach(
    {
        Set-Mailbox -Identity $_.username -EmailAddresses @{add="$($_.email)"}
    }
)

Dopo l’esecuzione dello script, non verrà visualizzato alcun output nella console. L’assenza di output significa che il nuovo indirizzo email è stato aggiunto correttamente. Ma come puoi essere sicuro che gli indirizzi email siano stati aggiunti?

Utilizzando lo stesso file CSV new_address.csv come riferimento, è possibile verificare se i nuovi indirizzi sono stati aggiunti utilizzando Import-Csv e ForEach.

Lo script di seguito importa i contenuti del file new_address.csv e li memorizza nella variabile $user_list. Quindi, utilizzando il metodo foreach(), PowerShell esegue un ciclo sull’intero elenco di utenti per verificare se il nuovo indirizzo email esiste nell’elenco degli indirizzi proxy della casella di posta. Se viene trovato, lo stato restituirà True; altrimenti, il risultato sarà False.

$user_list = Import-Csv .\new_address.csv

$user_list.foreach(
    {
        $emailObj = (Get-Mailbox -Identity $_.username).EmailAddresses
        if ($emailObj -contains $_.email) {
            Write-Host "$($_.username) --> $($_.email) --> TRUE"
        }
        else {
            Write-Host "$($_.username) --> $($_.email) --> FALSE"
        }
    }
)

Quando lo script di convalida viene eseguito, l’output dovrebbe apparire come mostrato nella schermata di seguito. Noterai nell’output che lo stato è tutto TRUE, il che significherebbe che i nuovi indirizzi email sono stati aggiunti con successo a ciascuna casella di posta.

Running the new email address verification

Invio previsioni meteorologiche giornaliere a una lista di distribuzione

In questo esempio, si presume di avere un file CSV contenente un elenco degli indirizzi email dei sottoscrittori e la loro area o posizione. Questi sottoscrittori si aspettano una email giornaliera contenente le previsioni del tempo per il giorno specifico della loro località. Dai un’occhiata all’esempio di CSV qui sotto con nome file subscribers.csv.

Weather forecast subscribers list

Il CSV qui sotto contiene solo due sottoscrittori. Uno a Los Angeles e uno a Manila.

Lo scopo è creare uno script che esegua le seguenti azioni:

  • Importa le informazioni sull’email e sull’area dal file subscribers.csv
  • Per ogni sottoscrittore:
    – Scarica l’immagine delle previsioni del tempo in base all’area del sottoscrittore da https://wttr.in/
    – Invia l’immagine delle previsioni del tempo come email all’indirizzo email del sottoscrittore.

Lo script qui sotto esegue le azioni elencate in precedenza. Devi solo modificare le prime tre variabili – $senderAddress, $smtpServer e $smtpPort. Quindi copia questo codice e salvalo come Send-WeatherInfo.ps1. Fai riferimento ai commenti sopra ogni sezione dello script per saperne di più su cosa fa il codice.

# INIZIA qui le impostazioni SMTP
$senderAddress = '<SENDER EMAIL ADDRESS HERE'
$smtpServer = '<SMTP RELAY SERVER HERE>'
$smtpPort = 25
# INIZIA qui le impostazioni SMTP

# Importa la lista di email degli abbonati
$subscriber_list = Import-Csv .\subscribers.csv

# Ottieni le previsioni del tempo e invia email
$subscriber_list.foreach(
    {
				
        # Costruisci l'URL per le informazioni meteo in base all'area
        $uri = ('<https://wttr.in/>' + $_.Area + '_u1F.png')
        # Ottieni l'immagine delle previsioni del tempo dell'area. Salva l'immagine come <AREA>.png
        $imageFile = (((Resolve-Path .\).Path) + "$($_.Area).png")
        Start-BitsTransfer $uri -Destination $imageFile

        # Crea l'oggetto allegato
        $attachment = New-Object System.Net.Mail.Attachment -ArgumentList $imageFile
        $attachment.ContentDisposition.Inline = $true
        $attachment.ContentDisposition.DispositionType = "Inline"
        $attachment.ContentType.MediaType = "image/png"
        $attachment.ContentId = "weatherImage"

        # Componi il messaggio
        $emailMessage = New-Object System.Net.Mail.MailMessage
        $emailMessage.From = $senderAddress
        $emailMessage.To.Add($_.Email)
        $emailMessage.Subject = ('Weather Forecast - ' + $_.Area)
        $emailMessage.IsBodyHtml = $true
        $emailMessage.Body = '<img src="cid:weatherImage">'
        $emailMessage.Attachments.Add($attachment)

        # Invia il messaggio
        Write-Output "Sending Weather Info to $($_.Email)"
				$smtp = New-Object Net.Mail.SmtpClient($smtpServer, $smtpPort)
        $smtp.Send($emailMessage)

        # Disponi degli oggetti
        $attachment.Dispose()
        $emailMessage.Dispose()
    }
)

Una volta eseguito lo script, verrà inviata una email a ogni abbonato simile all’esempio di screenshot dell’email sottostante.

Weather forecast for Manila sent as an email to the subscriber
Weather forecast for Los Angeles sent as an email to the subscriber

Riepilogo

Non ci sono limiti per i compiti in cui possono essere applicati Import-Csv e il ciclo ForEach. Finché il compito coinvolge una lista con colonne delimitate, puoi sicuramente approfondire questa potente combinazione.

In questo articolo, hai appreso come un file CSV è simile a un database. Hai anche imparato come utilizzare Import-Csv per l’importazione dei dati e come fare riferimento ai valori durante l’iterazione del ciclo ForEach.

I hope that with the many examples provided in this article, you now understand more of the Import-Csv and ForEach. And, that you would be able to use the knowledge you gained in this article in your administration and automation tasks.

Ulteriori letture

Source:
https://adamtheautomator.com/import-csv-and-the-foreach-loop/