معالجة بيانات CSV باستخدام الأمر Import-Csv و ForEach Loop في PowerShell

هل سبق لك أن قمت بنفس المهمة عدة مرات؟ مثل إنشاء مستخدمي Active Directory متعددين مستخدمًا واجهة المستخدم الرسومية لمستخدم واحد في كل مرة؟ أو ماذا عن تسجيل الدخول إلى خادم لحذف السجلات القديمة من بعض المجلدات المحددة؟ إذا كانت إجابتك نعم، فاعلم أنك لست وحدك. حان الوقت لاحتراف “Import-Csv” في PowerShell وحلقة الـ “foreach”.

لا يوجد شيء خاطئ في المهام اليدوية؛ فهي ضرورية في بعض الأحيان. ولكن عندما يتعلق الأمر بقراءة ومعالجة ملفات CSV، فإن أمر “Import-Csv” في PowerShell واستخدام حلقة الـ “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.
  • نظام التشغيل ويندوز باورشيل 5.1 أو باورشيل كور 6+
  • الوصول إلى Exchange Online (اختياري إذا كنت ستتبع التجربة عملية ذات الصلة بـ Exchange Online).

وضع استيراد CSV وحلقة ForEach في العمل

في الأقسام التالية ستجد العديد من الأمثلة حول كيفية استخدام cmdlet Import-Csv وحلقة ForEach التي قد تواجهها في سيناريوهات العمل الحقيقية. على الرغم من أن أمثلة استيراد CSV هذه تختلف تبعًا للهدف الذي تستخدم لأجله، إلا أنه من الأهمية بمكان فهم أن المفهوم والتقنية المستخدمة هما نفسهما.

قراءة وعرض السجلات من ملف CSV

ربما أبسط استخدام لـ cmdlet Import-Csv وحلقة ForEach هو قراءة السجلات من ملف وعرضها في وحدة التحكم. تشابه تركيبة ملف CSV بنية قاعدة البيانات. لديها رؤوس أعمدة، ويعتبر كل صف سجلًا.

على سبيل المثال، فيما يلي محتوى ملف يسمى employee.csv، والذي يتكون من ثلاثة أعمدة – EmployeeID و Name و Birthday، وأربعة سجلات.

CSV containing employee records

الكود أدناه يقوم باستيراد محتويات ملف employee.csv ثم يربط البيانات المستوردة بـ cmdlet ForEach-Object. ثم، سيقوم cmdlet 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)."
}

بمجرد حفظ البرنامج النصي، قم بتشغيله بواسطة استدعاء اسم الملف في PowerShell. عند تشغيل البرنامج النصي، يجب أن ترى إخراجًا مشابهًا للقطة الشاشة أدناه.

Imported CSV records displayed in the console

البحث وعرض السجلات من CSV

في المثال السابق، تعلمت كيفية قراءة وعرض جميع السجلات من ملف CSV. في هذا المثال، سيتم استخدام نفس ملف CSV employee.csv، ولكن هذه المرة، ستقوم بإنشاء وظيفة PowerShell للبحث عن رقم معرف الموظف في ملف CSV.

مقتطف الكود أدناه هو وظيفة PowerShell تسمى Find-Employee لديها معامل واحد فقط. اسم المعامل هو EmployeeID وهو يقبل قيمة رقم معرف الموظف المراد البحث عنه من الملف CSV.

قبل استخدام هذه الوظيفة، يجب استيرادها إلى جلسة PowerShell الخاصة بك أولاً. هناك طريقتان لاستيراد وظيفة Find-Employee إلى الذاكرة:

  1. نسخ الكود أدناه ولصقه في PowerShell.
  2. حفظ البرنامج النصي باسم Find-Employee.ps1 واستيراده باستخدام تقنية النقطة المصدرية.

ملاحظة: نوع حلقة الـ 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) {

            # إذا تم العثور على معرّف الموظف، قم بعرض السجل على وحدة التحكم.
            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 بالعناوين التالية:

  • servername – هذا هو اسم الخادم للاستعلام عنه.
  • disk – هذا هو حرف القرص الذي سيتم استرداد استخدامه للمساحة.
  • threshold – يحدد هذا الحد الأدنى بالغيغابايت. إذا كانت المساحة المتاحة في القرص أقل من هذه القيمة، سيظهر التقرير بحالة تحذير.

العينة أدناه توضح أن هناك أربع سجلات مدرجة. سيكون ملف 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.
  • حدد الخصائص المناسبة فقط للعرض.
    اسم الخادم – هو اسم النظام الذي يتم الاستعلام عنه.
    حرف القرص – الحرف المسند للقرص.
    الحجم (جيجابايت) – حجم القرص بوحدة جيجابايت.
    المساحة المتاحة (جيجابايت) – حجم المساحة المتاحة بوحدة جيجابايت.
    الحد الأدنى (جيجابايت) – الحد المحدد بوحدة جيجابايت.
    الحالة – إذا كانت قيمة المساحة المتاحة (جيجابايت) أقل من قيمة الحد الأدنى (جيجابايت) ، فإن الحالة المعادة هي ‘تحذير’. وإلا ، ستكون الحالة ‘طبيعية’.

بعد حفظ ملف النص النصي diskReport.ps1 ، فإنه الآن جاهز للتشغيل عن طريق استدعاء اسمه في PowerShell.

./diskReport.ps1

بمجرد تنفيذه ، يعرض اللقطة الشاشة أدناه نتائج النص النصي.

Disk space information gathered from multiple servers

يمكن أيضًا تصدير النتائج إلى CSV. يكون تصدير النتائج إلى CSV مفيدًا عندما يكون هناك حاجة لمشاركة التقرير لأنه يمكن إرسال ملف CSV المصدر أو تحميله إلى مشاركة الملفات أو موقع SharePoint. تأكد من الاطلاع على Export-Csv: الطريقة في PowerShell للتعامل مع ملفات CSV كمواطنين من الدرجة الأولى إذا كنت ترغب في مزيد من المعلومات حول التصدير إلى CSV.

إنشاء مستخدمي Active Directory المتعددين

في هذه النقطة ، يجب أن تكون لديك فكرة قوية حول استخدام Import-Csv و ForEach. يأخذ المثال التالي تعلمك قليلاً بإضافة أمر 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 و foreach للحصول على كائنات 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 أولاً.

يمكن معالجة القائمة في سكريبت PowerShell باستخدام الأمرين Import-Csv و ForEach في عملية واحدة. يوضح السكريبت أدناه كيفية القيام بذلك.

يقوم السكريبت أدناه بإستيراد محتويات ملف 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"
        }
    }
)

عند تشغيل نص التحقق ، يجب أن يكون الإخراج مشابهًا لما هو موضح في اللقطة المصورة أدناه. ستلاحظ في الإخراج أدناه أن الوضع هو صحيح بالكامل ، مما يعني أن عناوين البريد الإلكتروني الجديدة تمت إضافتها إلى كل صندوق بريد بنجاح.

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')
        # الحصول على صورة توقعات الطقس للمنطقة. حفظ الصورة باسم <AREA>.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/