Bir dizindeki tüm dosya ve klasörleri nasıl silebilirim?


662

C # kullanarak, bir dizindeki tüm dosya ve klasörleri nasıl silebilirim, ancak yine de kök dizini nasıl saklayabilirim?


11
DirectoryInfo'nun .Clean () gibi bir yöntemi olsaydı ne olurdu?
JL.

6
veya .DeleteFolders ve DeleteFiles yöntemleri.
JL.

18
Bir dosya kilitliyse (veya haklarınız yoksa) Silme işlemlerinizin kolayca bir istisna atabileceğini bilmek istersiniz. İstisnaların listesi için FileInfo.Delete dosyasına bakın.
Shane Courtrille

Yanıtlar:


833
System.IO.DirectoryInfo di = new DirectoryInfo("YourPath");

foreach (FileInfo file in di.GetFiles())
{
    file.Delete(); 
}
foreach (DirectoryInfo dir in di.GetDirectories())
{
    dir.Delete(true); 
}

Dizininizde çok sayıda dosya varsa, EnumerateFiles()daha verimlidir GetFiles(), çünkü kullandığınızda EnumerateFiles(), tüm koleksiyonu döndürmeden önce, numaralandırmaya başlamadan önce GetFiles()tüm koleksiyonu belleğe yüklemeniz gereken yerin aksine numaralandırmaya başlayabilirsiniz. Bu alıntıya buradan bakın :

Bu nedenle, birçok dosya ve dizinle çalışırken EnumerateFiles () daha verimli olabilir.

Aynısı EnumerateDirectories()ve için de geçerlidir GetDirectories(). Kod şöyle olur:

foreach (FileInfo file in di.EnumerateFiles())
{
    file.Delete(); 
}
foreach (DirectoryInfo dir in di.EnumerateDirectories())
{
    dir.Delete(true); 
}

Bu sorunun amacı için, kullanmak için gerçekten bir neden yoktur GetFiles()ve GetDirectories().


6
Stackoverflow.com/questions/12415105/… hakkında ne var "Directory.Delete çağırdığınızda ve bir dosya bu şekilde açık olduğunda, Directory.Delete tüm dosyaları siler ancak Directory.Delete RemoveDirectory çağırır bir" dizin boş değil " Silinmek üzere işaretlenmiş ancak gerçekte silinmemiş bir dosya olduğundan istisna atılır. "
Kiquenet

74
DirectoryInfo yavaştır, çünkü bu çok daha fazla veri toplar. BTW: Directory.Delete(path, true)
herkesle

57
@AcidJunkie, Bu söz konusu dizini de kaldıracak, oysa OP özellikle kök dizinin korunmasını ister.
Marc L.

5
Dosyalardan herhangi biri salt okunursa, bunun işe yaramayacağını unutmayın. Aramadan önce salt okunur bayrağını kaldırmanız gerekir file.Delete().
Ben

8
Alt dizinler dosya içeriyorsa bu işe yaramaz gibi görünüyor.
cdiggins

174

Evet, bunu yapmanın doğru yolu bu. Kendinize bir "Temizle" (veya "Boş" işlevi olarak adlandırmayı tercih ettiğim gibi) vermek istiyorsanız, bir uzantı yöntemi oluşturabilirsiniz.

public static void Empty(this System.IO.DirectoryInfo directory)
{
    foreach(System.IO.FileInfo file in directory.GetFiles()) file.Delete();
    foreach(System.IO.DirectoryInfo subDirectory in directory.GetDirectories()) subDirectory.Delete(true);
}

Bu daha sonra böyle bir şey yapmanıza izin verecektir ..

System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(@"C:\...");

directory.Empty();

4
Son satır, directory.Delete (true) yerine subDirectory.Delete (true) olmalıdır. Sadece kodu kesip yapıştırdım ve ana dizinin kendisini sildi. Kod için teşekkürler harika!
Aximili

26
EmptyC # 'da zaten var olan bir not string. Adında başka bir şey Emptygörürsem, nesnenin (veya dosya sisteminin) boolboş olup olmadığını söyleyen bir nesne vermek yerine değiştirirse şaşırırdım . Bu nedenle, isimle giderdim Clean.
Varsayılan

5
@Default: Bir türün bir özelliğe sahip olduğu gerçeğinin, başka (tamamen ilgisiz) bir türün buna sahip olup olmayacağı konusunda herhangi bir etkisi olması gerektiğini düşünmüyorum; ve fiiller olabilen sözcüklerin durumunu belirten özellikler ve işlevler için kural, bunlara önek eklemektir Is(yani, IsEmptyyerine Empty).
Adam Robinson

3
@AdamRobinson Sadece not etmek istedim. To bana , hangi Microsoft kendi kodunda sahip bir ağırlığa sahiptir do. Ama herkes yorumlayacaktır :)
Varsayılan

4
@simonhaines: Sorunun amacı dizini boşaltmak değil , dizini boşaltmak (yani içindeki her şeyi silmek ) idi.
Adam Robinson

77

Aşağıdaki kod klasörü özyinelemeli olarak temizler:

private void clearFolder(string FolderName)
{
    DirectoryInfo dir = new DirectoryInfo(FolderName);

    foreach(FileInfo fi in dir.GetFiles())
    {
        fi.Delete();
    }

    foreach (DirectoryInfo di in dir.GetDirectories())
    {
        clearFolder(di.FullName);
        di.Delete();
    }
}

Benim için çalıştı iken Directory.Delete (yol, true); klasör empy olmadığından şikayetçi
Jack Griffin

40
 new System.IO.DirectoryInfo(@"C:\Temp").Delete(true);

 //Or

 System.IO.Directory.Delete(@"C:\Temp", true);

1
İkinci seçenek olan Directory.Delete (String, Boolean) benim için çalıştı.
Stephen MacDougall

15
Bu, OP'nin özellikle saklanmasını istediğini kök dizini siler.
Marc L.

2
Deletedizin yoksa atar, bu yüzden Directory.Existsönce bir kontrol yapmak daha güvenli olur .
James

1
@James Directory.Existsyeterli değil; kontrolden sonra başka bir evre dizini yeniden adlandırmış veya kaldırmış olabilir. Daha güvenlidir try-catch.
andre_ss6

2
@Marv Basitçe ekleyerek dikkatli olun Directory.Createçünkü özyinelemenin Directory.Deletene yazık ki eşzamanlı olması garanti edilmez ..
Andrew Hanlon

38

LINQ için sevgiyi de gösterebiliriz :

using System.IO;
using System.Linq;

var directory = Directory.GetParent(TestContext.TestDir);

directory.EnumerateFiles()
    .ToList().ForEach(f => f.Delete());

directory.EnumerateDirectories()
    .ToList().ForEach(d => d.Delete(true));

Buradaki çözümümün performans göstermediğine dikkat edin, çünkü iki kez Get*().ToList().ForEach(...)aynı şeyi kullanıyorum IEnumerable. Bu sorunu önlemek için bir uzantı yöntemi kullanın:

using System.IO;
using System.Linq;

var directory = Directory.GetParent(TestContext.TestDir);

directory.EnumerateFiles()
    .ForEachInEnumerable(f => f.Delete());

directory.EnumerateDirectories()
    .ForEachInEnumerable(d => d.Delete(true));

Bu, uzantı yöntemidir:

/// <summary>
/// Extensions for <see cref="System.Collections.Generic.IEnumerable"/>.
/// </summary>
public static class IEnumerableOfTExtensions
{
    /// <summary>
    /// Performs the <see cref="System.Action"/>
    /// on each item in the enumerable object.
    /// </summary>
    /// <typeparam name="TEnumerable">The type of the enumerable.</typeparam>
    /// <param name="enumerable">The enumerable.</param>
    /// <param name="action">The action.</param>
    /// <remarks>
    /// “I am philosophically opposed to providing such a method, for two reasons.
    /// …The first reason is that doing so violates the functional programming principles
    /// that all the other sequence operators are based upon. Clearly the sole purpose of a call
    /// to this method is to cause side effects.”
    /// —Eric Lippert, “foreach” vs “ForEach” [http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx]
    /// </remarks>
    public static void ForEachInEnumerable<TEnumerable>(this IEnumerable<TEnumerable> enumerable, Action<TEnumerable> action)
    {
        foreach (var item in enumerable)
        {
            action(item);
        }
    }
}

1
Alt dizinleri de silmeye çalışıyorsanız, foreach (var dir in info.GetDirectories("*", SearchOption.AllDirectories).OrderByDescending(dir => dir.FullName.Length)) dir.Delete();yararlı olabilir.
Warty

1
Performanstan hoşlanıyorsanız , yöntemleri yerine directory.EnumerateFiles()ve directory.EnumerateDirectories()kullanmayı düşünün directory.Get*().
Tinister

1
Komik, kendi IEnumerable<T>.ForEach()uzantımın özet bir XML yorumu var, "İhlal! İhlal! Kirli!".
Marc L.

Hey, ikinci sebep nedir? 3'üncü? Vb.?
Bill Roberts

lol @RASX - seninle konuşuyor: "Eğer bu felsefi itirazlara katılmazsan ve bu kalıpta pratik değer bulmazsan, elbette, bu önemsiz tek astarı kendin yaz."
Bill Roberts

37

En basit yol:

Directory.Delete(path,true);  
Directory.CreateDirectory(path);

Bunun klasördeki bazı izinleri silebileceğini unutmayın.


9
bunun yoldaki tüm özel izinleri kaldıracağını unutmayın
Matthew Lock

6
Bu iki eylem arasında zaman aşımı süresi eklemeniz gerekir. bu kodu çalıştırmayı deneyin ve Exception alırsınız: while (true) {Directory.Delete (@ "C: \ Myfolder", true); Directory.CreateDirectory (@ "C: \ Myfolder"); }
RcMan

31
private void ClearFolder(string FolderName)
{
    DirectoryInfo dir = new DirectoryInfo(FolderName);

    foreach(FileInfo fi in dir.GetFiles())
    {
        try
        {
            fi.Delete();
        }
        catch(Exception) { } // Ignore all exceptions
    }

    foreach(DirectoryInfo di in dir.GetDirectories())
    {
        ClearFolder(di.FullName);
        try
        {
            di.Delete();
        }
        catch(Exception) { } // Ignore all exceptions
    }
}

Alt klasör olmadığını biliyorsanız, bunun gibi bir şey en kolay olabilir:

    Directory.GetFiles(folderName).ForEach(File.Delete)

Bu işlevi sistem geçici klasörünü silmek için kullandım. Ben sadece tüm istisnalar yoksaymak için Delete () ve IsReadOnly etrafında try-catch ekledi ve işe yaradı.
humbadlar

@humbads, bu yanıtı güncelleyebilir veya kodu buraya koyabilir misiniz ve değişikliklerinizi güncelleyeceğim?
zumalifeguard

13
System.IO.Directory.Delete(installPath, true);
System.IO.Directory.CreateDirectory(installPath);

3
yukarıdakiyle aynı: yolun sahip olduğu tüm özel izinleri kaldıracağını unutmayın.
hB0

8

Denediğim her yöntem, bir noktada System.IO hatalarıyla başarısız oldu. Aşağıdaki yöntem, klasör boş olsa da olmasa da, salt okunur olsa da olmasa da işe yarar.

ProcessStartInfo Info = new ProcessStartInfo();  
Info.Arguments = "/C rd /s /q \"C:\\MyFolder"";  
Info.WindowStyle = ProcessWindowStyle.Hidden;  
Info.CreateNoWindow = true;  
Info.FileName = "cmd.exe";  
Process.Start(Info); 

1
Dizinleri boşaltmaya gelince hep rd / s / q + mkdir'i tercih ederim.
Dawid Ohia

7
Bu, platformlar arası bir çözüm değildir. Unix benzeri sistemler açıkça cmd.exe'ye sahip değildir, .exe dosyalarını bile çalıştırmazlar. C # sadece Windows değil, aynı zamanda çapraz platform olan Mono da var.
Görünen Ad

1
@SargeBorsch soruda çapraz platform gereksinimi yoktu ve C # olması büyük olasılıkla çözüm Windows için kullanılacak. .NET fonksiyonlarını kullanmayan tek cevap gibi görünüyor, bu yüzden alternatif olarak oldukça değerli.
Alex Pandrea

7

İşte tüm mesajları okuduktan sonra sona erdiğim araç. Yapar

  • Silinebilecek her şeyi siler
  • Bazı dosyalar klasörde kalırsa false değerini döndürür

O ilgilenir

  • Salt okunur dosyalar
  • Silme gecikmesi
  • Kilitli dosyalar

İşlem istisnada durdurulduğundan Directory.Delete kullanmaz.

    /// <summary>
    /// Attempt to empty the folder. Return false if it fails (locked files...).
    /// </summary>
    /// <param name="pathName"></param>
    /// <returns>true on success</returns>
    public static bool EmptyFolder(string pathName)
    {
        bool errors = false;
        DirectoryInfo dir = new DirectoryInfo(pathName);

        foreach (FileInfo fi in dir.EnumerateFiles())
        {
            try
            {
                fi.IsReadOnly = false;
                fi.Delete();

                //Wait for the item to disapear (avoid 'dir not empty' error).
                while (fi.Exists)
                {
                    System.Threading.Thread.Sleep(10);
                    fi.Refresh();
                }
            }
            catch (IOException e)
            {
                Debug.WriteLine(e.Message);
                errors = true;
            }
        }

        foreach (DirectoryInfo di in dir.EnumerateDirectories())
        {
            try
            {
                EmptyFolder(di.FullName);
                di.Delete();

                //Wait for the item to disapear (avoid 'dir not empty' error).
                while (di.Exists)
                {
                    System.Threading.Thread.Sleep(10);
                    di.Refresh();
                }
            }
            catch (IOException e)
            {
                Debug.WriteLine(e.Message);
                errors = true;
            }
        }

        return !errors;
    }

6

Aşağıdaki kod dizini temizler, ancak kök dizini orada bırakır (özyinelemeli).

Action<string> DelPath = null;
DelPath = p =>
{
    Directory.EnumerateFiles(p).ToList().ForEach(File.Delete);
    Directory.EnumerateDirectories(p).ToList().ForEach(DelPath);
    Directory.EnumerateDirectories(p).ToList().ForEach(Directory.Delete);
};
DelPath(path);

6

kullandım

Directory.GetFiles(picturePath).ToList().ForEach(File.Delete);

eski resmi silmek için ve bu klasörde herhangi bir nesneye ihtiyacım yok


1
.ToList ()
Ben Power

5

FileInfo ve DirectoryInfo yerine File ve Directory ile sadece statik yöntemler kullanmak daha hızlı performans gösterir. ( C # 'da File ve FileInfo arasındaki fark nedir? bölümünde kabul edilen cevaba bakınız ). Yanıt, faydalı yöntem olarak gösterilir.

public static void Empty(string directory)
{
    foreach(string fileToDelete in System.IO.Directory.GetFiles(directory))
    {
        System.IO.File.Delete(fileToDelete);
    }
    foreach(string subDirectoryToDeleteToDelete in System.IO.Directory.GetDirectories(directory))
    {
        System.IO.Directory.Delete(subDirectoryToDeleteToDelete, true);
    }
}

5
private void ClearFolder(string FolderName)
{
    DirectoryInfo dir = new DirectoryInfo(FolderName);

    foreach (FileInfo fi in dir.GetFiles())
    {
        fi.IsReadOnly = false;
        fi.Delete();
    }

    foreach (DirectoryInfo di in dir.GetDirectories())
    {
        ClearFolder(di.FullName);
        di.Delete();
    }
}

3
string directoryPath = "C:\Temp";
Directory.GetFiles(directoryPath).ToList().ForEach(File.Delete);
Directory.GetDirectories(directoryPath).ToList().ForEach(Directory.Delete);

Mscorlib.dll dosyasında 'System.IO.IOException' türünde bir kural dışı durum oluştu, ancak kullanıcı kodunda işlenmedi Ek bilgi: Dizin boş değil.
kipusoep

3

Windows 7'de, Windows Gezgini ile el ile oluşturduysanız, dizin yapısı şuna benzer:

C:
  \AAA
    \BBB
      \CCC
        \DDD

Ve C: \ AAA dizinini temizlemek için orijinal soruda önerilen kodu çalıştırdığınızda, çizgi di.Delete(true)her zaman IOException ile başarısız olur. Muhtemelen Windows Gezgini'nde bir tür gecikme / önbellekleme nedeniyle.

Aşağıdaki kod benim için güvenilir bir şekilde çalışıyor:

static void Main(string[] args)
{
    DirectoryInfo di = new DirectoryInfo(@"c:\aaa");
    CleanDirectory(di);
}

private static void CleanDirectory(DirectoryInfo di)
{
    if (di == null)
        return;

    foreach (FileSystemInfo fsEntry in di.GetFileSystemInfos())
    {
        CleanDirectory(fsEntry as DirectoryInfo);
        fsEntry.Delete();
    }
    WaitForDirectoryToBecomeEmpty(di);
}

private static void WaitForDirectoryToBecomeEmpty(DirectoryInfo di)
{
    for (int i = 0; i < 5; i++)
    {
        if (di.GetFileSystemInfos().Length == 0)
            return;
        Console.WriteLine(di.FullName + i);
        Thread.Sleep(50 * i);
    }
}

Stackoverflow.com/questions/12415105/… hakkında ne var "Directory.Delete çağırdığınızda ve bir dosya bu şekilde açık olduğunda, Directory.Delete tüm dosyaları siler ancak Directory.Delete RemoveDirectory çağırır bir" dizin boş değil " Silinmek üzere işaretlenmiş ancak gerçekte silinmemiş bir dosya olduğundan istisna atılır. "
Kiquenet

@Kiquenet: Windows'ta bir sorun bulduk gibi görünüyor. Windows, silinmek üzere işaretlenmiş dosyaların listesine başvurabilir ve dizindeki tüm dosyalar silinmek üzere işaretlenmişse, dizinin boş olmadığını söylemeyin. Neyse benim WaitForDirectoryToBecomeEmpty () bir geçici çözümdür.
farfareast

2

Bu sürüm özyinelemeli çağrılar kullanmaz ve salt okunur sorunu çözer.

public static void EmptyDirectory(string directory)
{
    // First delete all the files, making sure they are not readonly
    var stackA = new Stack<DirectoryInfo>();
    stackA.Push(new DirectoryInfo(directory));

    var stackB = new Stack<DirectoryInfo>();
    while (stackA.Any())
    {
        var dir = stackA.Pop();
        foreach (var file in dir.GetFiles())
        {
            file.IsReadOnly = false;
            file.Delete();
        }
        foreach (var subDir in dir.GetDirectories())
        {
            stackA.Push(subDir);
            stackB.Push(subDir);
        }
    }

    // Then delete the sub directories depth first
    while (stackB.Any())
    {
        stackB.Pop().Delete();
    }
}

1

DirectoryInfo'nun GetDirectories yöntemini kullanın.

foreach (DirectoryInfo subDir in new DirectoryInfo(targetDir).GetDirectories())
                    subDir.Delete(true);

1

Aşağıdaki örnek bunu nasıl yapabileceğinizi göstermektedir. Önce bazı dizinler ve bir dosya oluşturur ve sonra bunları şu yollarla kaldırır Directory.Delete(topPath, true);:

    static void Main(string[] args)
    {
        string topPath = @"C:\NewDirectory";
        string subPath = @"C:\NewDirectory\NewSubDirectory";

        try
        {
            Directory.CreateDirectory(subPath);

            using (StreamWriter writer = File.CreateText(subPath + @"\example.txt"))
            {
                writer.WriteLine("content added");
            }

            Directory.Delete(topPath, true);

            bool directoryExists = Directory.Exists(topPath);

            Console.WriteLine("top-level directory exists: " + directoryExists);
        }
        catch (Exception e)
        {
            Console.WriteLine("The process failed: {0}", e.Message);
        }
    }

Https://msdn.microsoft.com/en-us/library/fxeahc5f(v=vs.110).aspx adresinden alınır .


1

Yukarıdaki sorunla başa çıkmanın en iyi yolu bu değildir. Ama alternatif bir tane ...

while (Directory.GetDirectories(dirpath).Length > 0)
 {
       //Delete all files in directory
       while (Directory.GetFiles(Directory.GetDirectories(dirpath)[0]).Length > 0)
       {
            File.Delete(Directory.GetFiles(dirpath)[0]);
       }
       Directory.Delete(Directory.GetDirectories(dirpath)[0]);
 }

0
DirectoryInfo Folder = new DirectoryInfo(Server.MapPath(path)); 
if (Folder .Exists)
{
    foreach (FileInfo fl in Folder .GetFiles())
    {
        fl.Delete();
    }

    Folder .Delete();
}

Daha spesifik olabilir ve bunun nasıl ve neden çalışması gerektiğini açıklayabilir misiniz?
Derin Dondurulmuş

3
Sadece kod içeren cevaplar uygun değildir. Sorunun nasıl ve neden çalışması / çözülmesi gerektiğini açıklamalısınız.
rdurand

0

bu klasörü nasıl sildiğimizi ve Metin kutusunu kullandığımızı kontrol edeceğimizi gösterir

using System.IO;
namespace delete_the_folder
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Deletebt_Click(object sender, EventArgs e)
    {
        //the  first you should write the folder place
        if (Pathfolder.Text=="")
        {
            MessageBox.Show("ples write the path of the folder");
            Pathfolder.Select();
            //return;
        }

        FileAttributes attr = File.GetAttributes(@Pathfolder.Text);

        if (attr.HasFlag(FileAttributes.Directory))
            MessageBox.Show("Its a directory");
        else
            MessageBox.Show("Its a file");

        string path = Pathfolder.Text;
        FileInfo myfileinf = new FileInfo(path);
        myfileinf.Delete();

    }


}

}

0
using System.IO;

string[] filePaths = Directory.GetFiles(@"c:\MyDir\");

foreach (string filePath in filePaths)

File.Delete(filePath);

0

Ana telefondan çağrı

static void Main(string[] args)
{ 
   string Filepathe =<Your path>
   DeleteDirectory(System.IO.Directory.GetParent(Filepathe).FullName);              
}

Bu yöntemi ekle

public static void DeleteDirectory(string path)
{
    if (Directory.Exists(path))
    {
        //Delete all files from the Directory
        foreach (string file in Directory.GetFiles(path))
        {
            File.Delete(file);
        }
        //Delete all child Directories
        foreach (string directory in Directory.GetDirectories(path))
        {
             DeleteDirectory(directory);
        }
        //Delete a Directory
        Directory.Delete(path);
    }
 }

0
 foreach (string file in System.IO.Directory.GetFiles(path))
 {
    System.IO.File.Delete(file);
 }

 foreach (string subDirectory in System.IO.Directory.GetDirectories(path))
 {
     System.IO.Directory.Delete(subDirectory,true); 
 } 

0

Klasörü silmek için bu, Metin kutusunu ve bir düğmeyi kullanan koddur using System.IO;:

private void Deletebt_Click(object sender, EventArgs e)
{
    System.IO.DirectoryInfo myDirInfo = new DirectoryInfo(@"" + delete.Text);

    foreach (FileInfo file in myDirInfo.GetFiles())
    {
       file.Delete();
    }
    foreach (DirectoryInfo dir in myDirInfo.GetDirectories())
    {
       dir.Delete(true);
    }
}

-2
private void ClearDirectory(string path)
{
    if (Directory.Exists(path))//if folder exists
    {
        Directory.Delete(path, true);//recursive delete (all subdirs, files)
    }
    Directory.CreateDirectory(path);//creates empty directory
}

2
Aşağıya bakın ... "silme ve yeniden oluşturma" tutma ile aynı değildir, tüm EKL özelleştirmeleri kaybolacaktır.
Marc L.

Ben umurumda değildi ve ACL özelleştirmeleri ve sonra oluşturulan klasör ile sorunları koştu beri buna çok benzer bir şey denedim Directory.CreateDirectory
SD JG içinde

-3

Yapmanız gereken tek şey ayarlamaktır optional recursive parameteriçin True.

Directory.Delete("C:\MyDummyDirectory", True)

.NET sayesinde. :)


3
Bu aynı zamanda dizinin kendisini de siler.
rajat

-4
IO.Directory.Delete(HttpContext.Current.Server.MapPath(path), True)

Bundan daha fazlasına ihtiyacın yok


2
Yanlış ... bu, kök dizini de silecektir.
L-Four
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.