حذف الملفات بكفاءة باستخدام PowerShell: Remove-Item و WMI

الحفاظ على مساحة القرص الحرة ضروري عند إدارة الخوادم والأنظمة. كمسؤولين، لا ترغب في أن تفاجأ بحالة “القرص ممتلئ”. لضمان عدم وقوعك في مشكلة، يجب عليك أن تتعلم كيفية استخدام PowerShell لحذف الملفات!

في هذا المقال، ستتعلم كل طريقة تقريبًا لحذف الملفات من الأنظمة الخاصة بك باستخدام PowerShell.

لنبدأ!

المتطلبات الأساسية

يقدم هذا المقال أمثلة باستخدام PowerShell، وإذا كنت تخطط لمتابعة، ستحتاج إلى ما يلي.

  • A computer that is running Windows 10 or above.
  • Windows PowerShell 5.1 أو PowerShell 7.0
  • A script editor such as Visual Studio Code, Atom, or Notepad++.

استخدام cmdlet Remove-Item لحذف الملفات

عندما تحتاج ببساطة إلى استخدام PowerShell لحذف ملف، فمن المحتمل أن تتعلم على الفور عن cmdlet Remove-Item. هذا الأمر هو المعيار الشائع لحذف الملفات باستخدام PowerShell.

باستخدام Remove-Item مع cmdlet Get-ChildItem لقراءة الملفات والمجلدات وأنابيب PowerShell القوية، يمكن أن تصبح الأمور سهلة حقًا.

ذات الصلة: Get-ChildItem: قائمة الملفات والسجلات والشهادات وأكثر من ذلك

هل تعلم أن لـ cmdlet Remove-Item اسمًا بديلًا وهو del؟ عند العمل في PowerShell، استخدام Remove-Item أو del سيؤدي إلى تنفيذ نفس الأمر.

استخدام PowerShell لحذف ملف

أول مثال سيكون الأكثر فائدة هو الأبسط – أي حذف ملف واحد. لحذف ملف واحد فقط، تحتاج فقط إلى استخدام الأمر التالي. الكود أدناه يقوم بحذف الملف C:\temp\random.txt.

Remove-Item -Path C:\temp\random.txt

تشغيل الكود أعلاه في PowerShell لن يظهر أي شيء على الشاشة إلا إذا واجه خطأ.

استخدام PowerShell لحذف جميع الملفات في مجلد

في هذا المثال، يقوم الكود أدناه بحذف جميع الملفات في مجلد. يستهدف أمر Get-ChildItem C:\temp باستخدام معامل -Path. المعامل -File يشير إلى أن النوع الوحيد للعناصر المراد تضمينها هو الملفات. أمر Get-ChildItem يتجاهل المجلدات.

Get-ChildItem -Path C:\temp -File | Remove-Item -Verbose

يجب أن يكون الناتج مشابهاً للصورة أدناه.

Successfully deleted all files in a folder

استخدام PowerShell لحذف جميع الملفات بشكل متكرر

المثال السابق قام بحذف الملفات فقط في المجلد C:\temp. إذا كنت بحاجة أيضًا لحذف الملفات داخل كل مجلد فرعي، فستحتاج إلى إضافة مفتاح التبديل -Recurse لأمر Get-ChildItem للحصول على جميع الملفات بشكل متكرر.

Get-ChildItem -Path C:\temp -File -Recurse | Remove-Item -Verbose

تشغيل الكود أعلاه يجبر PowerShell على البحث في جميع المجلدات الفرعية واسترداد قائمة جميع الملفات. يوضح الناتج أدناه أن الكود تمكن من حذف الملفات في المجلد العلوي؛ ومع ذلك، فشل في استرداد الملفات في المجلدات الفرعية.

Failed to retrieve files in sub-folders

التعامل مع مشكلة المسار الطويل

الخطأ المعروض أعلاه يشير إلى أن PowerShell “لم يتم العثور على جزء من المسار”. هذا الخطأ يشير إلى أن المسار الذي يحاول الأمر الوصول إليه غير موجود – وهذا أمر مضلل.

في هذه الحالة، كان الخطأ بسبب تجاوز المسار الذي يحاول Get-ChildItem قراءته لأقصى طول للمسار البالغ 260 حرفًا.

يُظهِر اللقطة الشاشة أدناه أن المسار أو الدليل ومجلداته الفرعية موجودة ويتم توجيه ملف نصي واحد بعنوان InTooDeep.txt في المجلد الفرعي الأقرب إلى الأسفل. تجميع الأحرف التي تشكل أسماء المجلدات المتداخلة يُخلق مشكلة مسار طويل.

Nested directories creating a long path name

في نظام التشغيل Windows PowerShell 5.1، هناك طريقة مؤقتة لحل مشكلة اسم المسار الطويل. الحل المؤقت هو استخدام الإصدار اليونيكود للمسار. بدلاً من تحديد المسار بهذا الشكل – C:\temp، استخدم الإصدار اليونيكود بهذا الشكل – ‘\\?\C:\temp’ للمجلدات الموجودة محليًا، أو ‘\\?\UNC\<اسم الكمبيوتر>\<مشاركة>\Temp’ إذا كان المجلد موجودًا في مسار UNC.

Get-ChildItem -Path '\\?\C:\temp' -File -Recurse | Remove-Item -Verbose

باستخدام الشفرة المعدلة أعلاه التي تتعامل مع اسم المسار الطويل، يُظهِر الإخراج أدناه أن PowerShell قرأ اسم المسار المتداخل بنجاح وحذف الملف.

Deleted the file with a long path name

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

إذا كانت المجلدات بحاجة أيضًا إلى حذفها، قم بإزالة معامل -File من أمر Get-ChildItem، ويجب أن يقوم PowerShell بحذف جميع العناصر، بما في ذلك الملفات والمجلدات.

استخدام PowerShell لحذف الملفات الأقدم من x أيام.

مثال آخر نموذجي لتنظيف مساحة القرص هو حذف الملفات التي تكون أقدم من عدد محدد من الأيام. هذا المثال مفيد لحذف ملفات السجل القديمة، مثل تلك التي يتم إنشاؤها بواسطة خوادم ويب IIS، لتحرير مساحة القرص.

في هذا المثال، هناك ملفات في c:\temp تكون أقدم من 14 يومًا. باستخدام البرنامج النصي أدناه، يتم عرض Name، CreationTime، و AgeInDays لكل ملف في c:\temp.

Get-ChildItem c:\temp | Select-Object Name,CreationTime,@{n='AgeInDays';e={(New-TimeSpan -Start $PSItem.CreationTime).Days}}

كما يمكنك رؤية في لقطة الشاشة أدناه، هناك ملفات تكون أقدم من 15 يومًا و 7 أيام و 0 أيام.

List of files in c:\temp

الآن بعد أن تعرفت على الملفات التي يجب حذفها، يمكنك إنشاء برنامج نصي لحذف الملفات التي تكون أقدم من عدد محدد من الأيام – في هذه الحالة، أقدم من 14 يومًا.

في البرنامج النصي أدناه، سيتم حذف الملفات في C:\temp التي تكون قيمة CreationTime لها أقدم من الحد المحدد.

السطر الأول يعرف المسار الذي ستبحث فيه Get-ChildItem. يتم حفظ المسار في المتغير $path. ثم، السطر الثاني هو حيث يتم تحديد الحد الزمني. قيمة المتغير $threshold هي عدد الأيام التي يجب أن يكون عمر الملف الذي سيتم حذفه أكبر منها.

السطر التالي من الكود بعد المتغير $threshold سوف يقوم بالآتي:

  • الحصول على مجموعة الملفات الموجودة في المجلد المحدد في المتغير $path. في هذا المثال، المسار هو C:\temp.
  • تصفية النتائج لتشمل فقط الملفات التي يكون CreationTime لها أقدم من عدد الأيام المحفوظ في المتغير $threshold. في هذا المثال، الحد المحدد هو 14 يومًا.
  • قم بتوجيه قائمة الملفات المُصفاة إلى قيمة Remove-Item لحذف تلك الملفات.
$path = 'C:\Temp'
$threshold = 14
Get-ChildItem -Path $path -File | Where-Object {$PSItem.CreationTime -lt (Get-Date).AddDays(-$threshold)} |Remove-Item -Verbose

عند تشغيل الشيفرة أعلاه، ستظهر لك نتيجة مشابهة لما هو موضح أدناه.

The script deleted the files older than 14 days

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

Get-ChildItem c:\temp | Select-Object Name,CreationTime,@{n='AgeInDays';e={(New-TimeSpan -Start $PSItem.CreationTime).Days}}

النتيجة أدناه تؤكد أن Remove-Item لم يقم بحذف الملفات الأحدث.

Newer files are left untouched

استخدام PowerShell لمطابقة وحذف أنماط الملفات

حذف جميع الملفات، بغض النظر عن الاسم أو النوع أو الامتداد ليس دائمًا الأفضل. في بعض الأحيان، تحتاج إلى استبعاد معين للملفات أو تضمينها في عملية الحذف.

يوضح المثال التالي كيفية حذف الملفات التي تتطابق مع اسم الملف *.LOG. أحد الطرق للقيام بذلك هو استخدام cmdlet Remove-Item مباشرةً باستخدام معامل -Include، كما هو موضح أدناه.

Remove-Item -Path C:\temp\* -Include *.log

طريقة أخرى، وربما تكون الطريقة الحذرة، هي استخدام Get-ChildItem أولاً لجمع قائمة الملفات التي سيتم حذفها. فقط عندما تكون راضيًا عن قائمة الملفات المراد حذفها، يمكنك أن توجه المجموعة أخيرًا إلى cmdlet Remove-Item.

على سبيل المثال، يحصل الشيفرة أدناه على ملفات *.LOG في c:\temp.

Get-ChildItem -Path C:\temp\* -Include *.log

نتيجةً للشيفرة أعلاه، يقوم Get-ChildItem بإرجاع قائمة الملفات المتطابقة مع اسم الملف *.LOG.

Only files matching the *.log filename is returned

ولكن، ماذا لو أردت استبعاد ملف يحتوي على الرقم 5 في اسمه؟ يمكنك القيام بذلك عن طريق إضافة معامل -Exclude كما هو موضح في الكود التالي.

Get-ChildItem -Path C:\temp\* -Include *.log -Exclude *5*

نظرًا لأنك استبعدت الملف بالرقم 5، فإن النتيجة مختلفة الآن. بالتحديد، الملف File_5.log لم يعد في القائمة، كما هو موضح أدناه.

The file File_5.log was excluded

عندما تكون راضيًا بالفعل عن مجموعة الملفات التي ينشئها الكود الخاص بك، يمكنك توجيه مجموعة الملفات إلى cmdlet Remove-Item لحذف تلك الملفات بشكل نهائي.

Get-ChildItem -Path C:\temp\* -Include *.log -Exclude *5* | Remove-Item -Verbose

بعد تشغيل الكود النهائي الخاص بك، ستكون قد حققت هدفك في حذف فقط الملفات التي اخترتها.

Deleting selected files

حذف الملفات باستخدام WMI في PowerShell

الآن بعد أن لديك فهم جيد لاستخدام cmdlet الشائعة Remove-Item لحذف الملفات، دعنا نتحول إلى حالة استخدام أكثر تقدمًا؛ باستخدام WMI.

تأتي PowerShell مع دعم لـ WMI. ودعم WMI يعني أنه يمكن استدعاء استعلامات وأساليب WMI من داخل PowerShell. نعم، WMI ليست مقصورة على نصوص Visual Basic التي كان يستخدمها المسؤولون في الأيام السابقة لنظام التشغيل Windows.

أصدرت Microsoft CIM cmdlets مخصصة لـ WMI في PowerShell 3.0. والـ CIM cmdlets التي ستستخدم لحذف الملفات هي Get-CimInstance و Invoke-CimMethod.

استخدام PowerShell و WMI لحذف ملف

تفترض هذه الأمثلة أنك تعرف مسار الملف المحدد الذي تريد حذفه. يتم استخدام cmdlet Get-CimInstance مع فئة Cim_DataFile لاسترداد معلومات الملف الذي سيتم حذفه، والذي هو C:\Temp\random.txt.

$file2delete = Get-CimInstance -ClassName Cim_DataFile -Filter "Name = 'C:\Temp\random.txt'"
 $file2delete

في الشيفرة أعلاه، يقبل المعامل -Filter استعلام بتنسيق WQL. يتطلب استخدام WQL الهروب من بعض الحروف بما في ذلك علامة الشرطة العكسية. ونظرًا لأن الحرف المستخدم للهروب في WQL هو أيضًا علامة الشرطة العكسية، فإن النتيجة هي ظهور حرف الشرطة العكسية مرتين – \\.

تشغيل الشيفرة أعلاه يعيد النتيجة المعروضة في العرض التوضيحي أدناه. يتم حفظ معلومات حول C:\Temp\random.txt في المتغير $file2delete.

Getting a file using WMI query and PowerShell

بمجرد استرداد معلومات الملف C:\Temp\random.txt، يمكن توجيه الكائن الناتج في المتغير $file2delete إلى cmdlet Invoke-CimMethod. يحتوي cmdlet Invoke-CimMethod على معامل يسمى -Name، الذي يمثل اسم طريقة فئة Cim_DataFile.

$file2delete | Invoke-CimMethod -Name Delete

كما هو موضح في لقطة الشاشة أدناه، يُظهر ReturnValue القيمة 0، مما يعني أن الأمر نجح.

File successfully deleted using WMI and PowerShell

لمعرفة بشأن رموز القيم المحتملة، يرجى الاطلاع على هذا الرابط – طريقة الحذف في فئة CIM_DataFile

بالإضافة إلى ذلك، يُظهر اللقطة الشاشة أدناه أنه بعد تشغيل الأمر Invoke-CimMethod لطريقة Delete()، قام CIM بإزالة الملف C:\Temp\random.txt فقط. ولم يقم بإزالة الملفات الأخرى.

C:\Temp\random.txt file was deleted

استخدام PowerShell و WMI لحذف كل الملفات في مجلد

في هذا المثال التالي، سوف نعرض لك كيفية حذف كل الملفات في مجلد باستخدام PowerShell و WMI. سيتم استخدام نفس الأوامر التي تم استخدامها في المثال السابق، وهي Get-CimInstance و Invoke-CimMethod. ولكن هذه المرة، ستقوم استعلام WQL بجلب جميع الملفات في المجلد بدلاً من ملف واحد محدد فقط.

في الكود التالي، يقوم الأمر Get-CimInstance بجلب جميع الملفات الموجودة في C:\temp. كما يمكن ملاحظة ذلك في الأسفل، يقوم الاستعلام بتصفية خصائص Drive و Path لفئة Cim_DataFile.

$file2delete = Get-CimInstance -ClassName Cim_DataFile -Filter "Drive = 'c:' AND Path = '\\temp\\'"

عند تشغيل الكود أعلاه، يتم حفظ المعلومات المُسترجعة حول الملفات في C:\temp في المتغير $file2delete. ويُظهر عرض قيمة/قيم المتغير $file2delete الناتج كما هو موضح أدناه.

List of all folders found in c:\temp using WMI

الآن، يمكن توجيه القيم المخزنة في المتغير $file2delete إلى Invoke-CimMethod لحذف جميع الملفات في c:\temp.

$file2delete | Invoke-CimMethod -Name Delete

تذكر أن رمز ReturnValue بقيمة 0 يعني نجاحًا ، ولكل ملف تم استدعاء طريقة الحذف عليه سيكون لديه رمز ReturnValue خاص به.

All files in c:\temp deleted using WMI

استخدام PowerShell و WMI لحذف الملفات بناءً على الامتداد

لقد رأيت في المثال السابق كيفية حذف جميع الملفات في مجلد بغض النظر عن الامتداد. ومع ذلك ، يمكنك أيضًا التحكم في الملفات التي يتم حذفها بناءً على الامتداد.

سوف تلاحظ في الكود أدناه ، في هذا المرة تحتوي الاستعلام على شرط مضاف (Name LIKE '%.log). هذا الشرط المضاف يعني أنه سيتم إرجاع الملفات التي تتطابق فقط مع الامتداد .LOG. علامة النسبة المئوية (%) هي عامل تشغيل WQL LIKE تعني “سلسلة من صفر أو أكثر من الحروف”.. من الناحية البرمجية ، تعد علامة النسبة المئوية (%) ما يعادل الاستبدال ، وهو علامة النجمة (*).

$file2delete = Get-CimInstance -ClassName cim_datafile `
-Filter "Drive = 'c:' AND Path = '\\temp\\' AND Name LIKE '%.log'"

$file2delete | Invoke-CimMethod -Name Delete

العرض التوضيحي أدناه يوضح أنه قبل تنفيذ الكود أعلاه ، هناك تسع ملفات *.LOG وملف واحد فقط *.TXT. بمجرد انتهاء تشغيل الكود ، يتم حذف الملفات *.LOG ويتبقى الملف *.TXT كملف وحيد في المجلد.

Deleting files by extension using WMI

مقارنة بين WMI و Remove-Item

حتى الآن في هذا البرنامج التعليمي ، حصلت على نظرة عامة على كيفية استخدام PowerShell لحذف الملفات. لقد تعلمت عن Remove-Item وأيضًا WMI. كلاهما يؤديان وظائف مماثلة ولكن بطرق مختلفة.

أي الطريقتين يجب أن تستخدم لحذف الملفات؛ Remove-Item أم WMI؟

استخدام أمر مدمج في PowerShell مثل Get-ChildItem و Remove-Item لاسترجاع وحذف الملفات يكون أسرع بكثير من استخدام WMI.

يوضح المثال أدناه الفرق عند استخدام WMI وأمر PowerShell المدمج للحصول على قائمة الملفات تحت الدليل C:\windows\web والدلائل الفرعية له.

## عرض جميع الملفات في C:\Windows\Web\ بشكل متكرر باستخدام Get-ChildItem
Measure-Command { Get-ChildItem C:\Windows\Web\ -Recurse}

## عرض جميع الملفات في C:\Windows\Web\ بشكل متكرر باستخدام Get-CimInstance واستعلام WMI
Measure-Command { Get-CimInstance -ClassName Cim_DataFile -Filter "Drive = 'c:' AND Path = '\windows\web\%'"}

عند تشغيل الكود أعلاه في PowerShell، سترى النتائج المشابهة للمثال أدناه.

Get-ChildItem vs. Get-CimInstance with WMI Query

كما ترى من النتائج المعروضة أعلاه، استغرقت عملية عرض الملفات في C:\windows\web زمنًا يقرب من عشرة أضعاف الوقت الذي استغرقه Get-CimInstance للاكتمال!

هل لاحظت أيضًا كيف يكون سطر Get-ChildItem أقصر بكثير من Get-CimInstance؟ ليس فقط تحصل على تنفيذ أسرع باستخدام Get-ChildItem، بل تستفيد أيضًا من كود أكثر نظافة وإيجازًا.

الخطوات التالية

في هذه المقالة، رأيت الطريقتين المختلفتين التي يمكنك استخدامهما في PowerShell لحذف الملفات باستخدام الأمر المدمج وWMI/CIM.

تذكر أنه يجب دائمًا استخدام أمر Get-ChildItem و Remove-Item لإزالة الملفات. هذه الأوامر المدمجة أكثر مرونة وأسهل وأسرع في الاستخدام من استخدام WMI.

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

القراءة الإضافية

Source:
https://adamtheautomator.com/powershell-to-delete-files/