עיבוד נתוני CSV עם Import-Csv ולולאת ForEach בפוורשל

האם חווית בעבר משימה דומה יותר מפעם אחת? לדוגמה, יצירת משתמשים מרשומת אחת בפעם בסביבת Active Directory באמצעות ממשק הגרפיקה (GUI)? או אולי כניסה לשרת כדי למחוק יומנים ישנים מתיקיות נבחרות? אם תשובתך היא "כן", תדע שאתה לא לבד. הגיע הזמן ללמוד את Import-Csv ולולאת foreach של PowerShell.

אין שום דבר שגוי עם משימות ידניות; מידי פעם זה נחוץ. אבל כשמדובר בקריאה ועיבוד של קבצי CSV, ניתן להשתמש בפקודה האזרחית של PowerShell, Import-Csv ובלולאה של foreach.

פקודת ה-Import-Csv של PowerShell היא דרך מצוינת לקרוא מידע ממקור ממודרג כגון קובץ CSV. ניתן להשתמש בלולאת foreach כדי לעבור על כל שורה בנתוני ה-CSV.

במאמר זה, תלמד כיצד להשתמש בשילוב זה עוצמתי כדי לאוטומציה של משימות גורפות, מובנות וחוזרות.

אם אתה חדש בתחום פקודת Import-Csv והלולאה של foreach של PowerShell, או אם ברצונך לקבל עדכונים על מה שכבר ידעת, ניתן לבקר בקישורים האלה כדי למד עוד.

ניהול קבצי CSV ב-PowerShell עם Import-Csv (לולאת foreach)

חזרה ליסודות: לולאת foreach של PowerShell

דרישות קדם

ישנם מספר דוגמאות והדגמות במאמר זה. כדי להתחיל, יהיו כמה דברים שיהיו צורך בהם יתרה מראש.

  • A script editor such as Visual Studio Code, Atom, or Notepad++. Use whichever one you’re comfortable with.
  • Windows PowerShell 5.1 או PowerShell Core 6+
  • גישה ל- Exchange Online (אופציונלי אם תעקוב אחר הדוגמה הקשורה ל- Exchange Online).

שימוש ב- Import-Csv וב- ForEach Loop

בקטעים הבאים ישנם מספר דוגמאות של שימוש בפקודת ה- Import-Csv ובלולאת ForEach שתיתקלו בהן בסצנריו אמיתיים. בעוד שהדוגמאות אלו ל- PowerShell של קובץ CSV מסוימות לכל מטרה, חשוב להבין שהרעיון והטכניקה המופעלים זהים.

קריאה והצגת רשומות מתוך CSV

אולי השימוש הבסיסי ביותר ב- Import-Csv ובלולאת ForEach הוא קריאת רשומות מקובץ והצגתן בקונסול. מבנה של קובץ CSV דומה לזה של מסד נתונים. לקובץ יש כותרות עמודות, וכל שורה נחשבת כ- רשומה.

לדוגמה, למטה תוכן הקובץ בשם employee.csv, אשר מורכב משלושה עמודות – מזהה_עובד, שם, ו- יום_הולדת, וארבע רשומות.

CSV containing employee records

הקוד למטה מייבא את תוכן קובץ ה- employee.csv ולאחר מכן מפנה את הנתונים שנייבאו לפקודת ForEach-Object. לאחר מכן, ForEach-Object תעבור דרך כל רשומה ב-CSV שניבא כדי להציג את הערכים המחוברים בקונסול. העתיקו את הקוד למטה ושמרו אותו בשם list-employee.ps1.

הערה: סוג הלולאת ForEach המשמשת בדוגמה זו למטה הוא הפקודה ForEach-Object. נא להפנות לקטע "פקודת ForEach-Object" ב-מאמר זה.

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

לאחר שהסקריפט נשמר, יש להפעיל אותו על ידי קריאה לשם הקובץ שלו בפוורשל. כאשר הסקריפט מופעל, יש לך צפייה בפלט דומה לצילום המסך שמופיע למטה.

Imported CSV records displayed in the console

חיפוש והצגת רשומות מ-CSV

בדוגמה הקודמת, למדת כיצד לקרוא ולהציג את כל הרשומות מ-CSV. בדוגמה זו, אותו קובץ CSV employee.csv יוכל לשמש, אך הפעם, תיצור פונקצית PowerShell לחיפוש של EmployeeID מתוך ה-CSV.

קטע הקוד למטה הוא פונקציית PowerShell בשם Find-Employee שיש לה פרמטר אחד בלבד. שם הפרמטר הוא EmployeeID והוא מקבל ערך של זיהוי העובד לחיפוש מתוך ה-CSV.

לפני שניתן יהיה להשתמש בפונקציה זו, יש לייבא אותה לשוליים של הפוורשל. ישנם שני אופנים לייבא את הפונקציה Find-Employee לזיכרון:

  1. העתקה והדבקה של הקוד לפוורשל למטה.
  2. שמירת הסקריפט כ-Find-Employee.ps1 וייבוא אותו באמצעות הטכניקה של dot-sourcing.

הערה: סוג הלולאת ForEach שנמצאת בדוגמה למטה היא ההצהרת ForEach. הפנה לסעיף "ההצהרת foreach" ב- מאמר זה.

Function Find-Employee {
    param (
        # הפרמטר מקבל את מזהה העובד לחיפוש.
        [Parameter(Mandatory)]
        $EmployeeID
    )

    # יבוא את תוכן קובץ employee.csv ואחסן אותו במשתנה $employee_list.
    $employee_list = Import-Csv .\employee.csv

    # לעבור דרך כל הרשומות ב-CSV
    foreach ($employee in $employee_list) {

        # בדוק אם מזהה העובד של הרשומה הנוכחית שווה לערך של הפרמטר EmployeeID.
        if ($employee.EmployeeID -eq $EmployeeID) {

            # אם נמצא את EmployeeID, הצג את הרשומה בקונסול.
            Write-Host "$($employee.Name), whose Employee ID is $($employee.EmployeeID), was born on $($employee.Birthday)."
        }
    }
}

פעם שקוד הפונקציה מיובא למודל PowerShell, יש לקרוא אותו על ידי קליטת שם הפונקציה כפי שמוצג למטה.

Find-Employee

כאשר הפונקציה מופעלת מבלי להשתמש בפרמטר EmployeeID, היא תבקש את ערך ה-EmployeeID לחיפוש. ראה את הפלט הדוגמא למטה.

Function to search a CSV file for a specific record

או, ניתן להפעיל את הפונקציה עם ערך הפרמטר EmployeeID המוגדר בזמן ריצה, כפי שמוצג למטה.

Find-Employee -EmployeeID 'E-2023'

קבלת שימוש בשטח האחסון ממספר שרתים

משימה רגילה אחת בין מנהלי המערכות היא למעקב אחר שימוש בשטח האחסון של מספר שרתים. במקום להתחבר לכל שרת כדי לבדוק את שימוש השטח בדיסק, ניתן ליצור רשימת CSV המכילה את שמות השרתים, אותיות הדרייב וסף. לאחר מכן, באמצעות PowerShell, יש לייבא את קובץ ה-CSV ולעבור דרך כל שורה כדי להריץ שאילתה.

כדי ליצור סקריפט שמשיג את שימוש המקום בדיסק משרתים מרוחקים, תחילה עליך ליצור את רשימת ה-CSV עם הכותרות הבאות:

  • שם_שרת – זהו שם השרת שיש לשאול.
  • דיסק – זהו האות של הדיסק שבו יושם לקח השימוש במקום.
  • סף – זה מגדיר את הסף בג'יגה-בייט. אם השטח הפנוי של הדיסק נמוך מערך זה, הדוח יציג מצב אזהרה.

הדוגמה למטה מראה שיש ארבעה רשומות מפורטות. הקובץ CSV שלך יהיה שונה בהתאם למספר השרתים או הדיסקים לקריאה.

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

לאחר שה-CSV הושלם, שמור את הקובץ כ־servers.csv. זה ישמש כרשימת הקלט שתיובא על ידי סקריפט PowerShell.

כדי לספק דוגמה לקבלת שימוש בשטח בדיסק, העתק את הקוד למטה אל עורך הסקריפט שלך ושמור אותו כ־diskReport.ps1. הסקריפט חייב להיות שמור באותו מיקום כמו נתיב ה-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'
            }
        }
    }
}

הסקריפט לעיל מבצע את הפעולות הבאות בעת ביצועו.

  • מייבא את קובץ ה-CSV בשם servers.csv ושומר אותו במשתנה $server_list.
  • עובר דרך רשימת השרתים שמאוחסנת במשתנה $server_list.
  • בכל איטרציה של לולאת ה־foreach, השורה הנוכחית מיוצגת על ידי המשתנה $server.
  • משיג את מידע הדיסק מהשרתים באמצעות הפקודה Get-WmiObject.
  • בחר רק במאפיינים הרלוונטיים להצגה.
    שם השרת – זהו שם המערכת שעליה מבצעים את השאילתה.
    אות הדיסק – האות המוקצה לדיסק.
    גודל (GB) – גודל הדיסק בגיגה-ביט
    חופשי (GB) – גודל המקום הפנוי בגיגה-ביט
    סף (GB) – הסף שהוגדר בגיגה-ביט
    סטטוס – אם ערך החופשי (GB) נמוך מערך הסף (GB), הסטטוס שמוחזר הוא ‘אזהרה‘. אחרת, הסטטוס יהיה ‘נורמלי

לאחר שמירת קובץ הסקריפט diskReport.ps1, הוא מוכן להפעלה על ידי קריאה לשמו ב-PowerShell.

./diskReport.ps1

ברגע שהוא מבוצע, הצילום מסך שלהלן מראה את פלט הסקריפט.

Disk space information gathered from multiple servers

ניתן לייצא את הפלט לקובץ CSV. הייצוא ל-CSV שימושי כאשר יש צורך לשתף את הדוח כיוון שניתן לשלוח את קובץ ה-CSV שיוצא בדוא"ל או להעלות אותו לשיתוף קבצים או לאתר SharePoint. אם ברצונך לקבל מידע נוסף על הייצוא ל-CSV, בדוק את Export-Csv: הדרך של PowerShell להתייחס לקבצי CSV כאזרחים מדרגה ראשונה.

יצירת משתמשים רבים ב-Active Directory

בשלב זה, כבר תהיה לך רעיון מוצק אודות השימוש בImport-Csv ו-ForEach. הדוגמה הבאה מרחיבה את הלמידה שלך עוד קצת על ידי הוספת ה-cmdlets New-ADUser ו-Get-ADUser לתערובת.

הנה, נניח שקיבלת קובץ CSV בשם new_employees.csv שמכיל את רשימת העובדים החדשים ממחלקת המשאבי אנוש. כל שורה בקובץ ה-CSV מייצגת משתמש שיש להוסיף, וכוללת את העמודות הבאות: שם פרטי, שם משפחה, מחלקה, מדינה, מספר עובד ו־משרד.

שם המשתמש ישתף פעולה מהאות הראשונה של שם הפרטי עם שם המשפחה (לדוגמה, bparr עבור המשתמש בוב פאר).

CSV file containing new employees information for on-boarding

לאחר שהקובץ CSV נשמר, הסקריפט למטה משתמש ב־Import-Csv כדי לקרוא את קובץ ה-CSV new_employees.csv. לאחר מכן, הוא עובר דרך כל שורה ומעביר את הערכים לפרמטרים המתאימים של 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
}

לאחר ביצוע הסקריפט, המשתמשים החדשים כבר צריכים להיות קיימים ב Active Directory. אך, זה נהג טוב לוודא כי חשבונות המשתמש נוצרו באמת.

באמצעות אותו קובץ CSV new_employees.csv כמקור, הסקריפט למטה יריץ ייבוא CSV ולכל אחת מהשורות יחפש עצמאות ADUser התואמות את אלו ברשימה.

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

הוספת כתובת דוא"ל חילופית לתיבת הדואר של Office 365

בניהול תיבת הדואר ב-Office 365, בקשות להוספת כתובות דוא"ל חילופיות למספר משתמשים אינן נדיבות. בדרך כלל, בבקשה כזו, המנהל מקבל רשימת משתמשים וכתובת הדוא"ל שיש להוסיף, דומה לדוגמה שבקובץ CSV שלמטה.

The new_address.csv file contents

שימו לב: לפני שתוכלו להריץ כל פקודות Exchange Online ב- PowerShell, עליכם להתחבר לסביבת הניהול של Exchange Online תחילה.

באמצעות הפקודות Import-Csv ו־ForEach בתוך סקריפט PowerShell, ניתן לעבד את הרשימה כולה בפעם אחת. הסקריפט למטה מראה כיצד ניתן לעשות זאת.

הסקריפט למטה מייבא את תוכן קובץ new_address.csv ושומר אותו במשתנה $user_list. לאחר מכן, בעזרת השיטה foreach(), PowerShell מבצעת לולאה דרך רשימת המשתמשים ומשתמשת בערכי התז של username ו־email בכל רשומה כדי להוסיף כתובת דוא"ל חדשה לכל תיבת דואר.

$user_list = Import-Csv .\new_address.csv

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

לאחר הרצת הסקריפט, לא תוצג הודעה בקונסול. אי הצגת תוצאות במסך מרמזת על הצלחת הוספת הכתובת הדוא"ל החדשה. אבל, איך ניתן לוודא שהכתובות הדוא"ל נוספו בהצלחה?

על ידי שימוש באותו קובץ CSV new_address.csv כמקור, אפשר לוודא האם הכתובות החדשות נוספו בעזרת Import-Csv ו־ForEach.

הסקריפט למטה מייבא את תוכן קובץ new_address.csv ושומר אותו במשתנה $user_list. לאחר מכן, בעזרת השיטה foreach(), PowerShell מבצעת לולאה דרך רשימת המשתמשים כדי לבדוק האם כתובת הדוא"ל החדשה קיימת ברשימת כתובות המשפחה של תיבת הדואר. אם היא נמצאת, התוצאה תהיה True; אחרת, התוצאה תהיה 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"
        }
    }
)

כאשר הסקריפט לאימות רץ, הפלט צריך להיראות כמו שמוצג בתמונת המסך למטה. תשים לב שבפלט למטה המצב הוא כולו TRUE, מה שאומר שכתובות האימייל החדשות נוספו בהצלחה לכל ארגז הדואר.

Running the new email address verification

שליחת תחזית מזג אוויר יומית לרשימת דיוור

בדוגמה זו, נניח שיש לך קובץ CSV המכיל רשימת כתובות האימייל של המנויים ואת אזורם או מיקומם. מנויים אלו מצפים לקבל אימייל יומי המכיל את תחזית המזג אוויר ליום המיוחד למיקומם. תבהר בCSV למטה בשם קובץ subscribers.csv.

Weather forecast subscribers list

ה-CSV למטה מכיל שני מנויים בלבד. אחד ב-לוס אנג'לס והשני ב-מנילה.

המטרה היא ליצור סקריפט שיבצע את הפעולות הבאות:

  • ייבא את מידע האימייל והאזור מקובץ ה-subscribers.csv
  • לכל מנוי:
    – הורד את תמונת תחזית המזג אוויר לפי האזור של המנוי מהכתובת https://wttr.in/
    – שלח את תמונת תחזית המזג אוויר כאימייל לכתובת האימייל של המנוי.

הסקריפט למטה מבצע את הפעולות שמוצגות לעיל. עליך רק לשנות את המשתנים הראשונים השלושה – $senderAddress, $smtpServer, ו- $smtpPort. לאחר מכן, העתק את הקוד ושמור אותו בשם Send-WeatherInfo.ps1. התייחס להערות מעל כל קטע בקוד כדי ללמוד עוד על תפקודו.

# התחלת הגדרות SMTP כאן
$senderAddress = '<SENDER EMAIL ADDRESS HERE'
$smtpServer = '<SMTP RELAY SERVER HERE>'
$smtpPort = 25
# התחלת הגדרות SMTP כאן

# יבוא רשימת כתובות האימייל של המנויים
$subscriber_list = Import-Csv .\subscribers.csv

# קבל תחזית מזג אוויר ושלח אימייל
$subscriber_list.foreach(
    {
				
        # בניית כתובת URL עבור מידע מזג אוויר בהתבסס על אזור
        $uri = ('<https://wttr.in/>' + $_.Area + '_u1F.png')
        # קבל את תמונת תחזית המזג אוויר של האזור. שמור את התמונה בשם <אזור>.png
        $imageFile = (((Resolve-Path .\).Path) + "$($_.Area).png")
        Start-BitsTransfer $uri -Destination $imageFile

        # צור אובייקט הצרכן
        $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"

        # קומפוז הודעה
        $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)

        # שלח הודעה
        Write-Output "Sending Weather Info to $($_.Email)"
				$smtp = New-Object Net.Mail.SmtpClient($smtpServer, $smtpPort)
        $smtp.Send($emailMessage)

        # השלך את האובייקטים
        $attachment.Dispose()
        $emailMessage.Dispose()
    }
)

כאשר הסקריפט מופעל, ישלח אימייל לכל מנוי דומה לדוגמה בצילום מסך האימייל למטה.

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

סיכום

אין גבול למשימות בהן ניתן להשתמש ב־Import-Csv ובלולאת ForEach. כל עוד המשימה כוללת רשימה עם עמודות מופרדות, אתה בטוח תבין את השילוב הזה החזק.

במאמר זה, למדת כיצד קובץ CSV דומה למסד נתונים. גם למדת כיצד להשתמש ב־Import-Csv לייבוא נתונים וכיצד להתייחס לערכים במהלך לולאת 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.

קריאה נוספת

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