Bagaimana cara menghapus seluruh direktori dengan PowerShell 2.0 secara rekursif?

308

Apa cara paling sederhana untuk secara paksa menghapus direktori dan semua subdirektori di PowerShell? Saya menggunakan PowerShell V2 di Windows 7.

Saya telah belajar dari beberapa sumber bahwa perintah yang paling jelas Remove-Item $targetDir -Recurse -Force,, tidak bekerja dengan benar. Ini termasuk pernyataan dalam bantuan online PowerShell V2 (ditemukan menggunakan Get-Help Remove-Item -Examples) yang menyatakan:

... Karena parameter Perulangan di cmdlet ini salah, perintah menggunakan cmdlet Get-Childitem untuk mendapatkan file yang diinginkan, dan menggunakan operator pipa untuk meneruskannya ke cmdlet Remove-Item ...

Saya telah melihat berbagai contoh yang menggunakan Get-ChildItem dan mem -pipe-nya ke Remove-Item , tetapi contoh-contoh itu biasanya menghapus beberapa set file berdasarkan filter, bukan seluruh direktori.

Saya mencari cara paling bersih untuk mengeluarkan seluruh direktori, file, dan direktori anak, tanpa menghasilkan pesan peringatan pengguna dengan menggunakan jumlah kode paling sedikit. Satu kalimat akan menyenangkan jika mudah dimengerti.

Matt Spradley
sumber
2
PowerShell, saya tahu, tapiRD /S /Q
Rubens Farias
kemungkinan duplikat: stackoverflow.com/questions/1667145/…
Rubens Farias
Saya rasa ini bukan duplikat. Saya meninjau 1667145 sebelum memposting. Ia bertanya mengapa PowerShell tidak mengatur parameter bool Perulangan dengan benar saat memanggil implementasi metode Remove-Item dari penyedia PowerShell kustom. Saya bertanya tentang perilaku Remove-Item yang berkaitan dengan penyedia sistem file bawaan.
Matt Spradley
2
"RD / S / Q" tampaknya tidak berfungsi di PowerShell - mengatakan "Hapus-Item: Parameter posisional tidak dapat ditemukan yang menerima argumen '/ q'."
BrainSlugs83
5
rdadalah alias untuk Remove-Itemdi PowerShell. cmd /c "rd /s /q"bekerja, meskipun.
codekaizen

Jawaban:

510
Remove-Item -Recurse -Force some_dir

memang berfungsi seperti yang diiklankan di sini.

rm -r -fo some_dir

adalah alias singkatan yang bekerja juga.

Sejauh yang saya mengerti, -Recurseparameter tidak berfungsi dengan benar ketika Anda mencoba menghapus satu set file yang difilter secara rekursif. Untuk membunuh satu dir dan semua yang ada di bawah ini sepertinya berfungsi dengan baik.

Joey
sumber
5
Aku pikir kamu benar. Saya mendapatkan "Tidak dapat menghapus item di 'direktori tertentu' karena sedang digunakan." kesalahan dan menganggap itu adalah masalah dengan algoritma rekursi dan pergi mencari solusinya. Ternyata saya memiliki proses yang saya buat sebelumnya dalam skrip yang berfungsi di direktori target. Ketika mengubah skrip untuk menunggu proses lainnya, perintah "Remove-Item -Recurse -Force" berfungsi. Selalu melihat ke cermin terlebih dahulu :)
Matt Spradley
15
Saya menemukan bahwa saya perlu menjalankan ini dua kali ketika dijalankan pada direktori yang berisi subdirektori. Pertama kali, akan ada banyak kesalahan "Direktori tidak kosong". Kedua kalinya, itu selesai tanpa kesalahan.
Kristopher Johnson
5
Kristopher Johnson, saya mendapatkan kesalahan serupa dengan berbagai alat pada Windows 7. Tampaknya panggilan hapus kembali lebih awal dari file atau folder yang sebenarnya dihapus, terkadang menyebabkan masalah. Ini tampaknya terjadi di Explorer, Far, cmd dan PowerShell.
Joey
2
@ Joey "Tampaknya panggilan hapus kembali lebih awal dari file atau folder yang sebenarnya dihapus, terkadang menyebabkan masalah." -> Untuk klarifikasi: folder induk tidak akan dihapus dan salah satu mendapat kesalahan berikut: "[folder induk] tidak dapat dihapus karena tidak kosong." Saya melihat ini terjadi terus-menerus pada drive jaringan (lambat). Satu-satunya solusi adalah yang lama: cmd /c rdseperti yang dinyatakan di bawah ini.
Davor Josipovic
6
Bagaimana dengan kesalahan "Direktori tidak kosong"? serverfault.com/questions/199921/powershell-remove-force Mungkin lebih baik dapatkan-childitem * -sertakan * .csv -recurse | hapus-item yang saya tidak tahu. Lihat stackoverflow.com/a/1668471/206730
Kiquenet
39

Saya menggunakan:

rm -r folderToDelete

Ini berfungsi bagi saya seperti pesona (saya mencurinya dari Ubuntu).

Tuan Jinn
sumber
Bukankah itu memerlukan cygwin, git, atau alat lain yang dapat mensimulasikan bash shell di Windows?
Pete
19
@Pete, tidak, itu tidak membutuhkan apa pun selain PowerShell. rmadalah alias untuk Remove-Itemdi konfigurasi default PowerShell ini. Periksa output Get-Alias rmuntuk lebih jelasnya. Ini -rmengambil keuntungan dari perilaku pencocokan parsial PowerShell pada parameter. Karena Remove-Itemhanya memiliki satu parameter yang dimulai dengan 'r' -Recurse,, -rcocok dengan itu. Dengan demikian, berikut semua akan bekerja sama: rm -r, rm -re, Remove-Item -Recurse. (Perhatikan bahwa tidak satu pun rm -rftidak rm -r -fakan berfungsi, tetapi rm -r -foakan. Tidak -rfcocok dengan parameter dan -fcocok lebih dari satu.)
chwarr
1
Bagaimana tentang itu. Alias ​​Powershell rm untuk "Remove-Item -Recurse -Force some_dir" berfungsi lebih baik daripada langsung menggunakan remove-item. Saya menerima kesalahan yang sama "Tidak dapat menghapus item di 'direktori tertentu'. Saya beralih dari hapus-item ke rm -r tanpa kesalahan !?
Greg
Menarik. Saya punya alat cygwin di kotak saya, dan telah mencoba rm -rf folderdan tentu saja gagal. Saya awalnya memilih sebagai jawaban (karena katanya Ubuntu). Berkat komentar oleh @chwarr, saya mencoba tanpa fdan mengambil alias daripada biner rm. Saya berharap Tuan akan memperbarui sumbernya (tidak yakin apakah Tuan tahu itu adalah alias atau benar-benar mengira itu adalah unix rm ;-)
Joshua Ball
2
Mungkin itu karena saya menggunakan -Rbukan -r(meskipun sejauh yang saya tahu PowerShell seperti sisa Windows tidak peka terhadap huruf besar maka seharusnya tidak membuat perbedaan) tapi saya mendapat kesalahan bahwa folder yang saya coba hapus adalah tidak kosong.
rbaleksandar
25

Ketika menghapus file secara rekursif menggunakan sederhana Remove-Item "folder" -Recursesaya kadang-kadang melihat kesalahan intermiten:[folder] cannot be removed because it is not empty.

Jawaban ini mencoba untuk mencegah kesalahan itu dengan menghapus file secara individual.

function Get-Tree($Path,$Include='*') { 
    @(Get-Item $Path -Include $Include -Force) + 
        (Get-ChildItem $Path -Recurse -Include $Include -Force) | 
        sort pspath -Descending -unique
} 

function Remove-Tree($Path,$Include='*') { 
    Get-Tree $Path $Include | Remove-Item -force -recurse
} 

Remove-Tree some_dir

Detail penting adalah penyortiran semua item dengan pspath -Descendingsehingga daun dihapus sebelum akar. Penyortiran dilakukan pada pspathparameter karena memiliki lebih banyak kesempatan bekerja untuk penyedia selain sistem file. The -Includeparameter hanya kenyamanan jika Anda ingin menyaring item untuk menghapus.

Ini dibagi menjadi dua fungsi karena saya merasa berguna untuk melihat apa yang akan saya hapus dengan menjalankan

Get-Tree some_dir | select fullname
John Rees
sumber
1
Saat menyelesaikan masalah menggunakan PowerShell di skrip build TFS, ini terbukti sebagai jawaban yang benar.
rcabr
Ini solusi untuk saya juga. Miliki diri Anda beberapa poin, orang baik saya!
Jammer
Bekerja untukku. Saya tidak bisa menghapus konten folder secara rekursif, tetapi solusi Anda berhasil untuk saya. terima kasih
SheldonH
Ini adalah solusi yang sangat kuat
Max Young
Saya tidak yakin mengapa jawaban yang diterima memiliki begitu banyak suara - Saya pribadi masih mendapatkan kesalahan intermiten remove-item -recursedi Powershell v5 sehingga solusi ini terbaik untuk saya.
JonoB
13
rm -r ./folder -Force    

... bekerja untukku

stevethecollier
sumber
11

Coba contoh ini. Jika direktori tidak ada, tidak ada kesalahan yang muncul. Anda mungkin memerlukan PowerShell v3.0.

remove-item -path "c:\Test Temp\Test Folder" -Force -Recurse -ErrorAction SilentlyContinue
steve
sumber
7

Gunakan perintah DOS old-school:

rd /s <dir>
Peter Mortensen
sumber
Jika ini adalah bagian dari skrip, Anda harus menggunakan /q(mode Diam, jangan tanya apakah ok untuk menghapus pohon direktori dengan / S) juga.
wildeyes
6

Untuk beberapa alasan, jawaban John Rees terkadang tidak berhasil dalam kasus saya. Tapi itu membawa saya ke arah berikut. Pertama saya mencoba untuk menghapus direktori secara rekursif dengan opsi buggy -recurse. Setelah itu saya turun ke setiap subdir yang tersisa dan menghapus semua file.

function Remove-Tree($Path)
{ 
    Remove-Item $Path -force -Recurse -ErrorAction silentlycontinue

    if (Test-Path "$Path\" -ErrorAction silentlycontinue)
    {
        $folders = Get-ChildItem -Path $Path –Directory -Force
        ForEach ($folder in $folders)
        {
            Remove-Tree $folder.FullName
        }

        $files = Get-ChildItem -Path $Path -File -Force

        ForEach ($file in $files)
        {
            Remove-Item $file.FullName -force
        }

        if (Test-Path "$Path\" -ErrorAction silentlycontinue)
        {
            Remove-Item $Path -force
        }
    }
}
joseose
sumber
Bisakah Anda mereproduksi kesalahan saat menjalankan fungsi saya? Saya ingin tahu sehingga saya bisa memperbaikinya.
John Rees
Maaf, tidak ingat pengaturan yang tepat. : / Saya pikir itu ketika banyak subdirektori di mana terlibat. Kebetulan panggilan ke "Remove-Item -force -recurse" tidak menghapus semua file dan dalam hal itu Remove-Tree terakhir gagal karena direktori tidak kosong. Itu sebabnya saya datang dengan solusi baru untuk pertama kali mencoba versi built-in kereta (-force) dan kemudian secara manual turun ke setiap direktori dan menghapus "secara manual" apa yang tersisa. Versi ini sedang digunakan secara teratur dan hingga saat ini berfungsi. Satu-satunya penyebab gagal adalah ketika sebuah program masih memegang pegangan ke direktori.
Sukai
5

Untuk menghindari kesalahan "Direktori tidak kosong" dari jawaban yang diterima, cukup gunakan perintah DOS lama yang baik seperti yang disarankan sebelumnya. Sintaks PS lengkap yang siap untuk disalin adalah:

& cmd.exe /c rd /S /Q $folderToDelete
Dejan
sumber
3
Masih memberikan kesalahan "Direktori tidak kosong" untuk folder !?
Oncel Umut TURER
2

Saya mengambil pendekatan lain yang terinspirasi oleh @ john-rees di atas - terutama ketika pendekatannya mulai gagal bagi saya di beberapa titik. Pada dasarnya, rekur ulang subtree dan urutkan file menurut panjang jalurnya - hapus dari yang terpanjang hingga yang terpendek

Get-ChildItem $tfsLocalPath -Recurse |  #Find all children
    Select-Object FullName,@{Name='PathLength';Expression={($_.FullName.Length)}} |  #Calculate the length of their path
    Sort-Object PathLength -Descending | #sort by path length descending
    %{ Get-Item -LiteralPath $_.FullName } | 
    Remove-Item -Force

Mengenai sihir -LiteralPath, berikut adalah gotchya lain yang mungkin mengenai Anda: https://superuser.com/q/212808

Peter McEvoy
sumber
2
del <dir> -Recurse -Force # I prefer this, short & sweet

ATAU

remove-item <dir> -Recurse -Force

Jika Anda memiliki direktori besar maka apa yang biasanya saya lakukan adalah

while (dir | where name -match <dir>) {write-host deleting; sleep -s 3}

Jalankan ini di terminal PowerShell lain dan itu akan berhenti ketika selesai.

Gajendra D Ambi
sumber
Saya akui ide Anda dengan pemantauan bisa bermanfaat, tetapi hampir tidak berbeda dengan hanya mencetak pesan setelah selesai, dan jika ada masalah menghentikan Penghapusan-Item, loop Anda tidak akan pernah berakhir.
Raúl Salinas-Monteagudo
@ RaúlSalinas-Monteagudo benar tetapi sudah pasti untuk skenario kasus penggunaan atau penggunaan tanpa pengawasan. Itu harus cukup kecil bagi seseorang untuk hanya mengingat dan mengetik saat bepergian dan tidak menjalankan file .ps1 yang canggih menjadi hanya sebuah direktori.
Gajendra D Ambi
2

Menghapus seluruh folder pohon kadang-kadang berfungsi dan kadang gagal dengan kesalahan "Direktori tidak kosong". Selanjutnya mencoba memeriksa apakah folder masih ada dapat mengakibatkan kesalahan "Akses Ditolak" atau "Akses Tidak Sah". Saya tidak tahu mengapa ini terjadi, meskipun beberapa wawasan dapat diperoleh dari posting StackOverflow ini .

Saya telah dapat mengatasi masalah ini dengan menentukan urutan item dalam folder yang dihapus, dan dengan menambahkan penundaan. Berikut ini berjalan dengan baik untuk saya:

# First remove any files in the folder tree
Get-ChildItem -LiteralPath $FolderToDelete -Recurse -Force | Where-Object { -not ($_.psiscontainer) } | Remove-Item Force

# Then remove any sub-folders (deepest ones first).    The -Recurse switch may be needed despite the deepest items being deleted first.
ForEach ($Subfolder in Get-ChildItem -LiteralPath $FolderToDelete -Recurse -Force | Select-Object FullName, @{Name="Depth";Expression={($_.FullName -split "\\").Count}} | Sort-Object -Property @{Expression="Depth";Descending=$true}) { Remove-Item -LiteralPath $Subfolder.FullName -Recurse -Force }

# Then remove the folder itself.  The -Recurse switch is sometimes needed despite the previous statements.
Remove-Item -LiteralPath $FolderToDelete -Recurse -Force

# Finally, give Windows some time to finish deleting the folder (try not to hurl)
Start-Sleep -Seconds 4

Artikel Microsoft TechNet Menggunakan Properti Terhitung di PowerShell sangat membantu saya dalam mendapatkan daftar sub-folder yang diurutkan berdasarkan kedalaman.

Masalah keandalan yang serupa dengan RD / S / Q dapat diselesaikan dengan menjalankan DEL / F / S / Q sebelum RD / S / Q dan menjalankan RD untuk kedua kalinya jika perlu - idealnya dengan jeda di antaranya (yaitu menggunakan ping seperti yang ditunjukkan di bawah).

DEL /F /S /Q "C:\Some\Folder\to\Delete\*.*" > nul
RD /S /Q "C:\Some\Folder\to\Delete" > nul
if exist "C:\Some\Folder\to\Delete"  ping -4 -n 4 127.0.0.1 > nul
if exist "C:\Some\Folder\to\Delete"  RD /S /Q "C:\Some\Folder\to\Delete" > nul
MikeOnline
sumber
1

Sangat sederhana:

remove-item -path <type in file or directory name>, press Enter
DusanV
sumber
Anda harus menawarkan contoh eksekusi juga.
terpisahkan
1

Trik lain yang bermanfaat:

Jika Anda menemukan banyak file dengan konvensi nama yang sama atau mirip (seperti file mac dengan nama awalan dot ... yang menarik file terkenal), Anda dapat dengan mudah menghapusnya dengan satu baris tunggal dari PowerShell seperti ini:

ls -r .* | rm

Baris ini akan menghapus semua file dengan titik di awal nama di dalam direktori saat ini, dan semua file dengan keadaan yang sama di dalam folder lain di dalam direktori ini juga. Berhati-hatilah saat menggunakannya. : D

Daniel Alberto Lepe Ayala
sumber
Kenapa tidak digunakan rm -rf .*? Saya tidak punya powerhell untuk diuji, tapi saya pikir itu akan berhasil.
Vini.g.fer
1
Mudah; jika Anda hanya menghapus "| rm" dari perintah, Anda dapat melihat seluruh panorama dari apa yang akan Anda hapus, setelah Anda yakin, Anda dapat menyelesaikan perintah.
Daniel Alberto Lepe Ayala
Oleh karena itu, Anda dapat menggunakan archivos que empiecen con punto, (como los de mac) pero que tengan propiedad de oculto, puedes usar: ls -r -h. * | rm
Daniel Alberto Lepe Ayala
1

Untuk menghapus konten lengkap termasuk penggunaan struktur folder

get-childitem $dest -recurse | foreach ($_) {remove-item $_.fullname -recurse}

Yang -recurseditambahkan untuk remove-itemmemastikan permintaan interaktif dinonaktifkan.

steve simon
sumber
-1
$users = get-childitem \\ServerName\c$\users\ | select -ExpandProperty name

foreach ($user in $users)

{
remove-item -path "\\Servername\c$\Users\$user\AppData\Local\Microsoft\Office365\PowerShell\*" -Force -Recurse
Write-Warning "$user Cleaned"
}

Tuliskan di atas untuk membersihkan beberapa file log tanpa menghapus direktori induk dan ini berfungsi dengan baik!

Tom Stevenson
sumber
-2
rm -r <folder_name>
c:\>rm -r "my photos"
pengguna3008
sumber
1
Tolong jelaskan lebih lanjut sehingga orang lain dapat belajar dari jawaban Anda
Nico Haase