مدیریت فایل با PowerShell: از Get-ChildItem تا کپی امن
آموزش عملی مدیریت فایل در PowerShell: فهرست، کپی، انتقال، حذف امن با WhatIf، فیلتر و الگوهای اسکریپت روزمرهٔ توسعهدهنده.
Founder & product engineer

وقتی باید صدها لاگ قدیمی را آرشیو کنید، خروجی بیلد را به پوشهٔ انتشار ببرید، یا در CI روی ویندوز فایلها را جابهجا کنید، File Explorer کافی نیست. PowerShell با provider فایلسیستم، اشیا را لوله میکند: اول پیدا کنید، بعد فیلتر کنید، بعد کپی/انتقال/حذف — با امکان WhatIf قبل از آسیب واقعی.
این راهنما روی cmdletهای روزمره متمرکز است و تفاوتهای ظریف Recurse، LiteralPath و کار روی مسیرهای دارای نویسهٔ خاص را نشان میدهد.

پاسخ کوتاه
فهرست: `Get-ChildItem` (علیاس `dir`/`ls`). ساخت: `New-Item`. کپی: `Copy-Item`. انتقال: `Move-Item`. حذف: `Remove-Item`. وجود مسیر: `Test-Path`. برای عملیات مخرب همیشه یکبار `-WhatIf` بزنید. فیلتر بازگشتی را ترجیحاً با `Get-ChildItem -Recurse -Filter` انجام دهید و نتیجه را به cmdlet بعدی لوله کنید — نه اینکه همهٔ منطق را در یک Copy-Item شلوغ بگذارید.
در PowerShell فایل «رشتهٔ مسیر» نیست؛ شیء است. اول لوله را درست کنید، بعد مقصد را.
چرا cmdlet بهجای فرمانهای قدیمی
هنوز `copy`، `move` و `del` در cmd کار میکنند و حتی در PowerShell بعضی علیاسها به cmdlet وصلاند. مزیت Get-ChildItem و دوستانش خروجی شیءدار است: میتوانید روی Length، LastWriteTime، Extension و Attributes فیلتر بزنید و گزارش بسازید. برای اتوماسیون قابلتست، این مدل پایدارتر از پارس کردن متن dir است.
کشف و فیلتر فایلها
powershell
Get-ChildItem C:\Work\myapp Get-ChildItem C:\Work\myapp -Recurse -File Get-ChildItem C:\Work\myapp -Recurse -Filter *.log Get-ChildItem C:\Work\myapp -Directory Get-ChildItem C:\Work\myapp -Force # شامل مخفی و سیستم
`-Filter` در provider فایلسیستم سریعتر از `-Include` روی بعضی مسیرها عمل میکند و هنگام Recurse برای الگوی نام مناسب است. برای شرطهای پیچیده از Where-Object استفاده کنید:
powershell
Get-ChildItem C:\Logs -Recurse -File -Filter *.log | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) -and $_.Length -gt 1MB }
ساخت پوشه و فایل
powershell
New-Item -ItemType Directory -Path C:\Work\release\artifacts -Force New-Item -ItemType File -Path C:\Work\release\README.txt -Value "build ok`n" -Force Test-Path C:\Work\release\artifacts
`-Force` روی Directory اگر وجود داشته باشد خطا نمیدهد (رفتار مطلوب اسکریپت). قبل از نوشتن روی فایل مهم، Test-Path و نسخهٔ پشتیبان عادت خوبی است.
Copy-Item: کپی آگاهانه
powershell
Copy-Item .\appsettings.json .\appsettings.backup.json Copy-Item .\dist\* C:\Deploy\myapp\ -Recurse -Force Get-ChildItem .\logs -Filter *.log | Copy-Item -Destination D:\archive\logs\
طبق مستندات Microsoft Learn، Copy-Item آیتم را در همان namespace کپی میکند و خودش برش نمیدهد. برای محدود کردن کپی بازگشتی بر اساس نام، اغلب بهتر است اول Get-ChildItem فیلتر کند و بعد به Copy-Item بدهد؛ تکیهٔ صرف به Include در Recurse رفتار گیجکنندهای داشته است.
powershell
# الگوی توصیهشده برای کپی گزینشی Get-ChildItem D:\temp\tree -Recurse -Filter ex* | Copy-Item -Destination D:\temp\out\
Move-Item و Rename-Item
powershell
Move-Item .\report.pdf D:\Reports\2026\ Get-ChildItem .\incoming -Filter *.csv | Move-Item -Destination D:\data\inbox\ Rename-Item .\draft.md final-notes.md
جابهجایی روی یک Volume معمولاً سریع و در حد بهروزرسانی metadata است؛ بین Volumeها عملاً کپی+حذف است و اتمی کامل نیست. برای جایگزینی فایل پیکربندی، الگوی رایج: نوشتن روی فایل موقت و سپس Move-Item روی نام نهایی.
powershell
Copy-Item .\config.new .\config.json.tmp -Force Move-Item .\config.json.tmp .\config.json -Force
Remove-Item بدون پشیمانی دیرهنگام
powershell
Remove-Item .\tmp\* -Recurse -WhatIf Remove-Item .\tmp\* -Recurse -Force Get-ChildItem .\logs -Filter *.tmp -Recurse | Remove-Item -WhatIf
مستندات Remove-Item هشدار میدهد که ترکیب Recurse با الگوی نوع فایل در Path گاهی رفتار غیرشهودی داشته؛ لوله از Get-ChildItem امنتر و خواناتر است. `-Confirm` و `$ConfirmPreference` را در اسکریپتهای اشتراکی جدی بگیرید.
مسیرهای خاص: LiteralPath و نویسهٔ وحشی
اگر نام فایل شامل `[` یا `]` باشد، Path معمولی آن را wildcard میفهمد. از `-LiteralPath` استفاده کنید:
powershell
Remove-Item -LiteralPath '.\file[1].txt' Get-Item -LiteralPath '.\file[1].txt'
برای مسیرهای طولانی ویندوز، گاهی پیشوند `\\?\` لازم است؛ اول ساختار پوشه را اصلاح کنید تا به سقف کلاسیک MAX_PATH وابسته نمانید، یا پشتیبانی مسیر بلند را در سیاست گروه فعال کنید.
خواندن و نوشتن محتوا
powershell
Get-Content .\app.log -Tail 50 Get-Content .\data.csv -TotalCount 5 'hello' | Set-Content .\out.txt -Encoding utf8 Get-ChildItem .\*.log | Select-String -Pattern 'ERROR' -SimpleMatch
برای فایلهای بزرگ، Get-Content بدون محدودیت حافظه را پر میکند؛ Tail و Stream یا ابزار تخصصی لاگ مناسبترند. Set-Content در برابر Add-Content برای بازنویسی کامل است.
جدول میانبر روزمره
| هدف | الگو |
|---|---|
| فهرست فایلها | Get-ChildItem -File |
| پوشههای تو در تو | Get-ChildItem -Recurse -Directory |
| کپی درخت | Copy-Item src dst -Recurse |
| حذف امن آزمایشی | Remove-Item ... -WhatIf |
| وجود مسیر | Test-Path |
| اندازهٔ پوشه تقریبی | (Get-ChildItem -Recurse -File | Measure-Object Length -Sum).Sum |
الگوی عملی: آرشیو لاگهای قدیمی
powershell
$src = 'C:\Logs\myapp' $dst = 'D:\Archive\myapp' New-Item -ItemType Directory -Path $dst -Force | Out-Null Get-ChildItem $src -Filter *.log -File | Where-Object LastWriteTime -lt (Get-Date).AddDays(-14) | ForEach-Object { Compress-Archive -Path $_.FullName -DestinationPath (Join-Path $dst ($_.BaseName + '.zip')) -Force Remove-Item -LiteralPath $_.FullName -Force }
این الگو را اول با -WhatIf روی Remove و با یک پوشهٔ آزمایشی خشک اجرا کنید. سپس در Task Scheduler بگذارید.
مجوز، مالکیت و فایل در حال استفاده
شکست Copy/Remove اغلب به ACL یا قفل فایل برمیگردد نه نحو فرمان. فرایند قفلکننده را با ابزار مدیریت فرایند پیدا کنید؛ بستن بیگدار IDE یا آنتیویروس گاهی لازم است. برای کپی با حفظ ACL پیشرفته، robocopy همچنان در سناریوهای مهاجرت حجیم قوی است و میتواند از PowerShell فراخوانی شود.
powershell
robocopy C:\Work\myapp D:\Backup\myapp /MIR /R:1 /W:1 /NFL /NDL
اشتباههای رایج
- حذف بازگشتی از ریشهٔ اشتباه بهخاطر متغیر خالی: همیشه قبل از Remove مقدار مسیر را لاگ کنید.
- فرض اینکه Move بین درایوها اتمی است.
- استفاده از cd و مسیر نسبی در تسک زمانبندیشده بدون Start in.
- چسباندن رمز یا توکن داخل فایلهایی که بعداً Copy-Item به اشتراک عمومی میفرستد.
- نادیده گرفتن -Force روی فایلهای ReadOnly و تعجب از خطا.
چه وقت از Explorer یا ابزار دیگر استفاده کنید
برای یکبار جابهجایی بصری چند فایل، Explorer سریعتر است. برای میلیونها فایل کوچک، robocopy یا ابزار تخصصی sync بهتر است. PowerShell نقطهٔ شیرین اتوماسیون قابلخواندن، فیلتر شیءدار و یکپارچگی با باقی اسکریپت استقرار است.
عمق عملیاتی بیشتر
توسعه روی ویندوز وقتی پایدار میشود که ابزار مشاهده، کنترل فرایند و زمانبندی را مثل مهارت کدنویسی جدی بگیرید.
بسیاری از اتلاف وقت روزانه نه از کمبود دانش زبان برنامهنویسی، بلکه از ندیدن مصرف حافظه، قفل فایل و سرویس خاموش است.
قبل از نصب ابزار شخص ثالث، قابلیت توکار ویندوز را امتحان کنید؛ مستندات Microsoft Learn معمولاً مسیر رسمی و پشتیبانیشده را نشان میدهد.
عادت کنید برای هر مشکل یک یادداشت کوتاه بنویسید: نشانه، زمان، PID، و فرمان یا ابزاری که استفاده کردید.
این یادداشتها در تیم به پایگاه دانش تبدیل میشوند و از تکرار دیباگ کور جلوگیری میکنند.
قدرت واقعی وقتی است که Task Manager، Resource Monitor، Event Viewer و PowerShell را در یک جریان واحد به کار ببرید.
اگر فقط یک پنجره را باز میکنید و حدس میزنید، همان چرخهٔ ریبوت بیدلیل تکرار میشود.
برای کارهای تکراری، بهجای حافظهٔ انسانی از Task Scheduler و اسکریپت نسخهٔکنترلشده استفاده کنید.
مجوز حداقل را رعایت کنید؛ اجرای همیشگی با Administrator ریشهٔ بسیاری از عادتهای ناامن است.
در نهایت، محیط توسعهٔ خوب آن است که شکست را سریع دیده، محدود و قابلبازگشت میکند — نه اینکه همه چیز را هر بار از صفر نصب کنید.
وقتی اپلیکیشن پاسخ نمیدهد، اول صبر کوتاه و مشاهدهٔ CPU و دیسک مفیدتر از End Task فوری است؛ شاید در حال نوشتن فایل یا انتظار شبکه باشد.
Analyze wait chain در Task Manager کمک میکند ببینید فرایند بهخاطر وابستگی به فرایند دیگر متوقف شده یا واقعاً حلقهٔ معیوب دارد.
Resource Monitor جزئیات دستهٔ دیسک و شبکه را نشان میدهد که در نمای سادهٔ Task Manager دیده نمیشود.
برای مصرف حافظه، تفاوت Working Set و Commit را بشناسید تا فقط با یک عدد بزرگ نترسید یا برعکس مشکل نشتی را نادیده نگیرید.
PowerShell با Get-Process و Get-Counter برای نمونهبرداری تکرارپذیر مناسب است و خروجیاش را میتوان لاگ کرد.
در محیط حرفهای، ریبوت باید آخرین گزینه باشد نه اولین Reflex؛ ریبوت علت را پاک میکند و یادگیری را میکشد.
ابزارهای عیبیابی توکار مثل Reliability History و Windows Memory Diagnostic برای الگوی زمانی خطا ارزش دارند.
اگر مشکل بعد از بهروزرسانی شروع شده، همبستگی تاریخ وصله با Event Log را قبل از بازنصب کامل بررسی کنید.
اسکریپتهای نگهداری را با مسیر مطلق و حساب کممجوز در Task Scheduler بگذارید و نتیجه را در فایل لاگ ببینید.
همکاری با تیم پشتیبانی وقتی سریع میشود که PID، نام دقیق فرایند، و اسکرین از Performance را ضمیمه کنید نه فقط «سیستم کند است».
ویندوز برای توسعهدهنده یک مانع نیست اگر لایهٔ مشاهده و کنترل را یاد بگیرید؛ همین مهارتها روی سرور ویندوزی هم برمیگردد.
از طرفی، وابستگی افراطی به GUI بدون فرمان خط فرمان، خودکارسازی و CI را ضعیف میکند.
تعادل سالم این است: GUI برای کشف، PowerShell برای تکرار، و مستندسازی برای تیم.
در پروژههای چندسیستمی، مرز واضح بین ابزار ویندوز و ابزار WSL از تداخل PATH و نسخههای تکراری جلوگیری میکند.
هر ماه یکبار فهرست سرویسهای غیرضروری استارتآپ و تسکهای زمانبندیشده را مرور کنید؛ رشد خاموش آنها منابع را میخورد.
نکتهٔ تکمیلی برای پایداری محیط این است که تغییرات سیستم را کوچک و قابلبرگشت نگه دارید و همیشه مسیر بازگشت داشته باشید.
قبل از تغییر سیاست اجرا یا نصب درایور آزمایشی، یک نقطهٔ بازیابی یا حداقل یادداشت نسخهٔ قبلی ابزارها تهیه کنید.
در دیباگ شبکهٔ محلی، ابتدا از localhost و سپس از نشانی واقعی استفاده کنید تا لایهٔ مشکل جدا شود.
برای کارهای فایل حجیم، بهجای کپی دستی تکراری از اسکریپت و لاگ استفاده کنید تا خطا قابلپیگیری باشد.
اگر ابزار توکار جواب نداد، آنگاه سراغ ابزار پیشرفتهتر بروید؛ ترتیب مهم است چون دادهٔ اولیه را از دست نمیدهید.
همین ترتیب را در تیم آموزش دهید تا نیروی تازهوارد هم از ریبوت اول شروع نکند.
در عمل، زنجیرهٔ عیبیابی خوب از مشاهدهٔ زنده شروع میشود، به لاگ تاریخی میرسد، و با یک تغییر کوچک قابلبرگشت ادامه پیدا میکند.
اگر در همان قدم اول نرمافزار را reinstall کنید، متغیرهای زیادی را همزمان جابهجا کردهاید و علت مبهم میماند.
برای توسعهدهنده، ثبت نسخهٔ ابزار، زمان وقوع و پیام خطا بخش از کار حرفهای است نه کار اضافی.
ویندوز وقتی پیشبینیپذیر میشود که سرویسها، تسکهای زمانبندی و استارتآپ را مثل inventory کد مدیریت کنید.
هر چه این inventory شفافتر باشد، اثر جانبی آپدیت و نصب پکیج جدید کمتر غافلگیرتان میکند.
همچنین برای کارهای خودکار، خروجی را به فایل یا رویداد بنویسید تا موفقیت خاموش با شکست خاموش اشتباه نشود.
این عادتها هزینهٔ اولیه دارند ولی در هفتههای پرترافیک بیلد و انتشار، زمان را برمیگردانند.
اگر تازهوارد تیم هستید، همین ابزارهای توکار را در روز اول با یک سناریوی ساختگی تمرین کنید تا در حادثه واقعی دستپاچه نشوید.
در محیطهایی که هم ویندوز و هم لینوکس دارید، یک فرهنگ مشترک برای نامبردن فرایند، پورت و زمان رویداد بسازید.
زبان مشترک عیبیابی، بیشتر از یکسانسازی سیستمعامل، همکاری را سریع میکند.
خلاصه
مدیریت فایل در PowerShell حول کشف (Get-ChildItem)، تأیید (Test-Path)، تغییر (Copy/Move/Rename) و حذف محتاطانه (Remove + WhatIf) میچرخد. فیلتر را زود انجام دهید، LiteralPath را برای نامهای خاص به یاد داشته باشید، و عملیات مخرب را اول خشک تست کنید. با همین پایه میتوانید نگهداری روزانه و گامهای CI ویندوز را قابلاعتماد کنید.
سوالات متداول
فرق -Filter و -Include چیست؟
Filter معمولاً در سطح provider و کارآمدتر است و یک الگو میگیرد. Include/Exclude روی نتایج بعد از حل Path اعمال میشوند و با Recurse باید با دقت استفاده شوند.
چطور حجم یک پوشه را ببینم؟
با Measure-Object روی Length فایلهای Recurse؛ برای نمایش خوانا مقدار را بر 1MB یا 1GB تقسیم کنید.
آیا Get-ChildItem فایل مخفی را نشان میدهد؟
بهصورت پیشفرض نه؛ `-Force` را اضافه کنید.
منابع و مراجع
- Copy-Item — Microsoft Learn: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/copy-item
- Move-Item — Microsoft Learn: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/move-item
- Remove-Item — Microsoft Learn: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/remove-item
- Get-ChildItem — Microsoft Learn: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem
Author
Soheil Ebrahimpour is the founder of FutureForge. He works on product design, architecture, and getting custom software into production.
Related notes
If you are unsure about architecture or the build path, we can talk about the project.
Describe the problem and the constraints. If there is a fit, we will schedule a conversation.




