ディレクトリ内のすべてのファイルとフォルダを削除するにはどうすればよいですか?


662

C#を使用して、ディレクトリからすべてのファイルとフォルダーを削除しながら、ルートディレクトリを保持するにはどうすればよいですか?


11
DirectoryInfoに.Clean();のようなメソッドがあれば何がいいでしょう。
JL。

6
または.DeleteFolders、およびDeleteFilesメソッド。
JL。

18
ファイルがロックされている場合(または権限がない場合)、削除は非常に簡単に例外をスローする可能性があることに注意してください。例外のリストについては、FileInfo.Deleteを参照してください。
シェーンコートリル、2009

回答:


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); 
}

ディレクトリに多くのファイルが含まれている可能性がある場合は、を使用すると、コレクション全体を返す前に列挙を開始できるため、コレクションを列挙する前にコレクション全体をメモリにロードする必要があるため、EnumerateFiles()より効率的です。ここでこの引用を参照してください:GetFiles()EnumerateFiles()GetFiles()

したがって、多くのファイルとディレクトリを使用している場合、EnumerateFiles()の方が効率的です。

同じことが、にも適用されるEnumerateDirectories()GetDirectories()。したがって、コードは次のようになります。

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

この質問の目的のために、実際にGetFiles()and を使用する理由はありませんGetDirectories()


6
stackoverflow.com/questions/12415105/…とは何ですか?「Directory.Deleteを呼び出してファイルがそのように開かれている場合、Directory.Deleteはすべてのファイルの削除に成功しますが、Directory.DeleteがRemoveDirectoryを呼び出すと、「ディレクトリは空ではありません」削除対象としてマークされているが実際には削除されていないファイルがあるため、例外がスローされました。」
Kiquenet 2013

74
DirectoryInfoは他の多くのデータを収集するため、低速です。ところで: Directory.Delete(path, true)すべての面倒を見るでしょう:)
AcidJunkie 14

57
@AcidJunkie、それは問題のディレクトリも削除しますが、OPはルートディレクトリを保持するように特に要求します。
マークL.

5
いずれかのファイルが読み取り専用の場合、これは機能しないことに注意してください。を呼び出す前に、読み取り専用フラグを削除する必要がありfile.Delete()ます。
ベン

8
サブディレクトリにファイルが含まれている場合、これは機能しないようです。
cdiggins

174

はい、それが正しい方法です。自分に "クリーン"(または、私はそれを "Empty"関数と呼びたい)を提供したい場合は、拡張メソッドを作成できます。

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);
}

これにより、次のようなことができるようになります。

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

directory.Empty();

4
最後の行は、directory.Delete(true)ではなくsubDirectory.Delete(true)である必要があります。コードをカットアンドペーストするだけで、メインディレクトリ自体が削除されました。それは素晴らしいコードをありがとう!
Aximili

26
EmptyC#には既に存在することに注意してくださいstring。他の名前が付いたものを見つけEmptyた場合、それがオブジェクト(またはファイルシステム)を変更したbool場合、それが空かどうかを示すメッセージを表示する代わりに、驚かれることでしょう。そのため、私は名前で行きCleanます。
デフォルトの

5
@デフォルト:あるタイプにプロパティがあるという事実は、別の(完全に関連のない)タイプにそれがあるべきかどうかに関係があるはずだとは思いません。また、動詞にもなり得る単語の状態を示すプロパティと関数の規則は、それらの前にIs(つまり、IsEmptyではなくEmpty)を付けることです。
Adam Robinson

3
@AdamRobinsonそれを書き留めたかっただけです。ために、私、何マイクロソフトがそのコードに持ってすることは、いくつかのベアリングを持っています。しかし、それは誰もが解釈するためのものです:)
デフォルトの

4
@simonhaines:問題のポイントは、ディレクトリ自体を削除するのではなく、ディレクトリを空にする(つまり、ディレクトリ内のすべてを削除する)ことでした。
アダムロビンソン

77

次のコードは、フォルダーを再帰的にクリアします。

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();
    }
}

Directory.Delete(path、true);の間に私のために働いた フォルダーが空ではなかったと不満を投げた
Jack Griffin

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

 //Or

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

1
2番目のオプションであるDirectory.Delete(String、Boolean)は私にとってはうまくいきました。
Stephen MacDougall 2013年

15
これにより、OPが保持するようにOPから具体的に要求されたルートディレクトリが削除されます。
Marc L.

2
Deleteディレクトリが存在しない場合はスローされるため、Directory.Exists最初にチェックを行う方が安全です。
ジェームズ

1
@ジェームズだけDirectory.Existsでは不十分です。チェック後、別のスレッドがディレクトリの名前を変更または削除した可能性があります。それはより安全try-catchです。
andre_ss6 2016年

2
@Marv慎重に単に追加することでDirectory.Create、再帰があるためDirectory.Delete、残念ながら...同期であることが保証されていません
アンドリュー・ハンロンを

38

LINQへの愛を示すこともできます。

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));

私が使用していますので、ここに私のソリューションは、パフォーマンスではないことに注意してGet*().ToList().ForEach(...)同じ生成するIEnumerable二回を。この問題を回避するために拡張メソッドを使用します。

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));

これは拡張メソッドです:

/// <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
また、サブディレクトリも削除しようとしている場合は、foreach (var dir in info.GetDirectories("*", SearchOption.AllDirectories).OrderByDescending(dir => dir.FullName.Length)) dir.Delete();役に立ちます。
Warty

1
パフォーマンスが好きな場合は、メソッドの代わりにdirectory.EnumerateFiles()およびを使用することを検討してください。directory.EnumerateDirectories()directory.Get*()
Tinister 2014

1
おかしい、私の独自のIEnumerable<T>.ForEach()拡張機能には、「違反!違反!不潔!」というXMLの概要コメントがあります。
Marc L.

2つ目の理由は何ですか?3番目?等。?
ビルロバーツ

笑@RASX-彼はあなたに話している:「あなたがこれらの哲学的な異論に同意せず、このパターンに実用的な価値を見出すなら、是非とも、先に進んでこの些細なワンライナーを自分で書いてください。」
ビルロバーツ

37

最も簡単な方法:

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

これにより、フォルダの一部の権限が消去される場合があることに注意してください。


9
これにより、パスにあった特別な権限が削除されることに注意してください
Matthew Lock

6
これら2つのアクションの間にタイムアウトを追加する必要があります。このコードを実行しようとすると、例外が発生します:while(true){Directory.Delete(@ "C:\ Myfolder"、true); Directory.CreateDirectory(@ "C:\ Myfolder"); }
RcMan 2017年

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
    }
}

サブフォルダがないことがわかっている場合は、次のようなものが最も簡単です。

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

この機能を使用して、システムの一時フォルダーをクリアしました。Delete()とIsReadOnlyの周辺にtry-catchを追加して、すべての例外を無視したところ、うまくいきました。
ハンバーズ

@humbads、この回答を更新できますか、またはコードをここに配置してください。変更内容で更新しますか?
zumalifeguard

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

3
上記と同じ:これにより、パスが持っていた特別な権限がすべて削除されることに注意してください。
hB0 2016年

8

私が試したすべての方法は、ある時点でSystem.IOエラーで失敗しました。次のメソッドは、フォルダーが空かどうか、読み取り専用かどうかなど、確かに機能します。

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
ディレクトリを空にする場合、私は常にrd / s / q + mkdirを好みます。
ダウィドオヒア2014年

7
これはクロスプラットフォームのソリューションではありません。Unixライクなシステムには、明らかにcmd.exeがなく、.exeファイルも実行しません。C#はWindowsだけではなく、クロスプラットフォームのMonoもあります。
表示名

1
@SargeBorsch質問にはクロスプラットフォームの要件はありませんでした。C#であるため、Windowsでソリューションが使用される可能性が最も高くなります。これは.NET関数を使用しない唯一の回答のようです。そのため、代替手段としては非常に価値があります。
Alex Pandrea

7

これが私がすべての投稿を読んだ後に終わったツールです。します

  • 削除可能なすべてを削除します
  • フォルダにファイルが残っている場合はfalseを返します

扱っている

  • 読み取り専用ファイル
  • 削除遅延
  • ロックされたファイル

プロセスは例外で中止されるため、Directory.Deleteは使用しません。

    /// <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

次のコードはディレクトリをクリーンアップしますが、ルートディレクトリはそのままにしておきます(再帰的)。

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

使った

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

古い画像を削除し、このフォルダにオブジェクトは必要ありません


1
.ToList()が必要かどうかわからない
Ben Power

5

FileInfoおよびDirectoryInfoの代わりにFileおよびDirectoryで静的メソッドのみを使用すると、より高速に実行されます。(で受け入れ答えを参照C#でファイルとのFileInfoの違いは何を?)。回答はユーティリティメソッドとして表示されます。

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);

タイプ 'System.IO.IOException'の例外がmscorlib.dllで発生しましたが、ユーザーコードでは処理されませんでした追加情報:ディレクトリが空ではありません。
kipusoep

3

Windows 7では、Windowsエクスプローラーで手動で作成した場合、ディレクトリ構造は次のようになります。

C:
  \AAA
    \BBB
      \CCC
        \DDD

そして、元の質問で提案されたコードを実行して、ディレクトリC:\ AAAをクリーンアップします。 di.Delete(true)と、BBBを削除しようとすると常にIOException "The directory is not empty"で失敗します。これはおそらく、Windowsエクスプローラーでの何らかの遅延/キャッシングが原因です。

次のコードは私にとって確実に機能します:

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/…とは何ですか?"Directory.Deleteを呼び出し、そのような方法でファイルが開かれている場合、Directory.Deleteはすべてのファイルの削除に成功しますが、Directory.DeleteがRemoveDirectoryを呼び出すと、「ディレクトリは空ではありません」削除対象としてマークされているが実際には削除されていないファイルがあるため、例外がスローされました。」
Kiquenet 2013

@Kiquenet:Windowsで問題が見つかったようです。Windowsは削除対象としてマークされたファイルのリストを調べた可能性があり、ディレクトリ内のすべてのファイルが削除対象としてマークされている場合は、ディレクトリが空でないとは言わないでください。とにかく、私のWaitForDirectoryToBecomeEmpty()は回避策です。
13

2

このバージョンは再帰呼び出しを使用せず、読み取り専用の問題を解決します。

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のGetDirectoriesメソッドを使用します。

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

1

次の例は、その方法を示しています。最初にいくつかのディレクトリとファイルを作成し、次にそれらを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から取得されます


1

これは上記の問題に対処する最良の方法ではありません。しかし、それは別のものです...

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();
}

もっと具体的に説明して、これがどのように、そしてなぜ機能するのか説明してください。
ディープフローズン

3
コードのみの回答は適していません。あなたはそれがどのようにそしてなぜ問題を解決/解決すべきかを説明する必要があります。
rdurand 2013

0

これは、フォルダーを削除し、それをチェックする方法を示します。テキストボックスを使用します。

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

メインからの呼び出し

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

このメソッドを追加

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

フォルダを削除するには、これはテキストボックスとボタンを使用したコードです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
以下を参照してください...「削除と再作成」は保持と同じではなく、ACLのカスタマイズはすべて失われます。
マークL.

ACLのカスタマイズについて気にしていなかったのでこれに非常に似たものを試してみましたが、フォルダーが後で作成されないという問題に遭遇しましたDirectory.CreateDirectory
SDのJG、

-3

あなたがすべき唯一のことはに設定optional recursive parameterすることTrueです。

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

.NETに感謝します。:)


3
これにより、ディレクトリ自体も削除されます。
rajat 2013

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

それ以上は必要ありません


2
間違い...これもルートディレクトリを削除します。
L-Four
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.