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

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

في هذا المقال، ستتعلم كل الطرق لإزالة الملفات من أنظمتك باستخدام بويرشيل.

لنبدأ!

الشروط المسبقة

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

  • A computer that is running Windows 10 or above.
  • ويندوز بويرشيل 5.1 أو بويرشيل 7.0
  • A script editor such as Visual Studio Code, Atom, or Notepad++.

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

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

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

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

هل تعلم أن أمر Remove-Item له اختصار باسم del? عند العمل في بويرشيل، استخدام Remove-Item أو del سيقوم بتشغيل نفس الأمر.

استخدام بويرشيل لحذف ملف

أول مثال يكون الأكثر فائدة هو الأبسط – أي، حذف ملف واحد. لحذف ملف واحد فقط، تحتاج فقط لاستخدام الأمر أدناه. يقوم الكود أدناه بحذف الملف 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\<computername>\<share>\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 يومًا. باستخدام النص أدناه، يتم عرض اسم، وقت الإنشاء، وعمر بالأيام لكل ملف في 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 الذين يكون وقت الإنشاء لهم أقدم من الحد المحدد.

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

السطر التالي بعد متغير $threshold سي:

  • الحصول على مجموعة الملفات الموجودة في المجلد المحدد في متغير $path. في هذا المثال، المسار هو C:\temp.
  • تصفية الإخراج لتضمين فقط الملفات التي يكون وقت الإنشاء لها أقدم من عدد الأيام المحفوظ في متغير $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

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

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

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

Deleting selected files

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

الآن بعد أن لديك فهم جيد لاستخدام أمر 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

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

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

C:\Temp\random.txt file was deleted

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

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

في الكود التالي، يقوم cmdlet 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. علامة النسبة (%) هي عامل LIKE WQL تعني “سلسلة تتألف من صفر أو أكثر من الأحرف”. من الناحية البرمجية، علامة النسبة (%) هي ما يعادل البادئة العامة، والتي هي علامة النجمة (*).

$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؟

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

المثال أدناه يوضح المقارنة عند استخدام WMI و cmdlet 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-ChildItem أقصر بكثير من Get-CimInstance? لا تحصل فقط على تنفيذ أسرع باستخدام Get-ChildItem، بل تستفيد أيضًا من كود أنظف وأقصر.

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

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

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

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

قراءة متعمقة

Source:
https://adamtheautomator.com/powershell-delete-file/