Wie kann ich mit C # alle Dateien und Ordner aus einem Verzeichnis löschen und trotzdem das Stammverzeichnis behalten?
Wie kann ich mit C # alle Dateien und Ordner aus einem Verzeichnis löschen und trotzdem das Stammverzeichnis behalten?
Antworten:
System.IO.DirectoryInfo di = new DirectoryInfo("YourPath");
foreach (FileInfo file in di.GetFiles())
{
file.Delete();
}
foreach (DirectoryInfo dir in di.GetDirectories())
{
dir.Delete(true);
}
Wenn Ihr Verzeichnis möglicherweise viele Dateien enthält, EnumerateFiles()
ist dies effizienter als GetFiles()
, da Sie bei Verwendung EnumerateFiles()
mit der Aufzählung beginnen können, bevor die gesamte Sammlung zurückgegeben wird, GetFiles()
anstatt die gesamte Sammlung in den Speicher zu laden, bevor Sie mit der Aufzählung beginnen. Sehen Sie dieses Zitat hier :
Wenn Sie mit vielen Dateien und Verzeichnissen arbeiten, kann EnumerateFiles () daher effizienter sein.
Gleiches gilt für EnumerateDirectories()
und GetDirectories()
. Der Code wäre also:
foreach (FileInfo file in di.EnumerateFiles())
{
file.Delete();
}
foreach (DirectoryInfo dir in di.EnumerateDirectories())
{
dir.Delete(true);
}
Für die Zwecke dieser Frage gibt es wirklich keinen Grund, GetFiles()
und zu verwenden GetDirectories()
.
Directory.Delete(path, true)
wird sich um alles kümmern :)
file.Delete()
.
Ja, das ist der richtige Weg. Wenn Sie sich eine "Clean" -Funktion (oder, wie ich es lieber nennen möchte, "Empty" -Funktion) geben möchten, können Sie eine Erweiterungsmethode erstellen.
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);
}
Auf diese Weise können Sie so etwas wie ... tun.
System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(@"C:\...");
directory.Empty();
Empty
in C # vorhanden ist, z string
. Wenn ich etwas anderes mit dem Namen sehen Empty
würde, wäre ich überrascht, wenn es das Objekt (oder das Dateisystem) modifizieren würde, anstatt mir ein zu geben bool
, das besagt, ob es leer ist oder nicht. Aus diesem Grund würde ich mit dem Namen gehen Clean
.
Is
(dh IsEmpty
nicht Empty
) ein Präfix voranzustellen .
Der folgende Code löscht den Ordner rekursiv:
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();
}
}
new System.IO.DirectoryInfo(@"C:\Temp").Delete(true);
//Or
System.IO.Directory.Delete(@"C:\Temp", true);
Delete
wird geworfen, wenn das Verzeichnis nicht existiert, daher wäre es sicherer, zuerst eine Directory.Exists
Überprüfung durchzuführen.
Directory.Exists
ist nicht genug; Nach der Überprüfung hat möglicherweise ein anderer Thread das Verzeichnis umbenannt oder entfernt. Es ist sicherer zu try-catch
.
Directory.Create
da die Rekursion Directory.Delete
leider nicht garantiert synchron ist ..
Wir können auch Liebe für LINQ zeigen :
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));
Beachten Sie, dass meine Lösung hier nicht performant ist, da ich sie verwende Get*().ToList().ForEach(...)
, die dieselbe IEnumerable
zweimal generiert . Ich verwende eine Erweiterungsmethode, um dieses Problem zu vermeiden:
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));
Dies ist die Erweiterungsmethode:
/// <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);
}
}
}
foreach (var dir in info.GetDirectories("*", SearchOption.AllDirectories).OrderByDescending(dir => dir.FullName.Length)) dir.Delete();
hilfreich sein.
directory.EnumerateFiles()
und directory.EnumerateDirectories()
anstelle der directory.Get*()
Methoden verwenden.
IEnumerable<T>.ForEach()
Erweiterung hat einen zusammenfassenden XML-Kommentar: "Verletzung! Verletzung! Unrein!".
Der einfachste Weg:
Directory.Delete(path,true);
Directory.CreateDirectory(path);
Beachten Sie, dass dadurch möglicherweise einige Berechtigungen für den Ordner gelöscht werden.
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
}
}
Wenn Sie wissen, dass es keine Unterordner gibt, ist so etwas möglicherweise am einfachsten:
Directory.GetFiles(folderName).ForEach(File.Delete)
Bei jeder Methode, die ich ausprobiert habe, sind sie irgendwann mit System.IO-Fehlern fehlgeschlagen. Die folgende Methode funktioniert mit Sicherheit, auch wenn der Ordner leer ist oder nicht, schreibgeschützt oder nicht usw.
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);
Hier ist das Tool, mit dem ich nach dem Lesen aller Beiträge geendet habe. Es tut
Es behandelt
Directory.Delete wird nicht verwendet, da der Prozess ausnahmsweise abgebrochen wird.
/// <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;
}
Der folgende Code bereinigt das Verzeichnis, lässt jedoch das Stammverzeichnis dort (rekursiv).
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);
ich benutzte
Directory.GetFiles(picturePath).ToList().ForEach(File.Delete);
Zum Löschen des alten Bildes brauche ich kein Objekt in diesem Ordner
Die Verwendung nur statischer Methoden mit Datei und Verzeichnis anstelle von DateiInfo und VerzeichnisInfo ist schneller. (Siehe akzeptierte Antwort unter Was ist der Unterschied zwischen File und FileInfo in C #? ). Antwort als Dienstprogrammmethode angezeigt.
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);
}
}
string directoryPath = "C:\Temp";
Directory.GetFiles(directoryPath).ToList().ForEach(File.Delete);
Directory.GetDirectories(directoryPath).ToList().ForEach(Directory.Delete);
Wenn Sie es in Windows 7 gerade manuell mit Windows Explorer erstellt haben, ähnelt die Verzeichnisstruktur der folgenden:
C:
\AAA
\BBB
\CCC
\DDD
Führen Sie den in der ursprünglichen Frage vorgeschlagenen Code aus, um das Verzeichnis C: \ AAA, die Zeile, zu bereinigen di.Delete(true)
Wenn Sie schlägt beim Versuch, BBB zu löschen immer mit der IOException "Das Verzeichnis ist nicht leer" fehl. Dies liegt wahrscheinlich an Verzögerungen / Caching im Windows Explorer.
Der folgende Code funktioniert für mich zuverlässig:
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);
}
}
Diese Version verwendet keine rekursiven Aufrufe und löst das schreibgeschützte Problem.
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();
}
}
Das folgende Beispiel zeigt, wie Sie das tun können. Es erstellt zuerst einige Verzeichnisse und eine Datei und entfernt sie dann über 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);
}
}
Es stammt von https://msdn.microsoft.com/en-us/library/fxeahc5f(v=vs.110).aspx .
Es ist nicht der beste Weg, um mit dem oben genannten Problem umzugehen. Aber es ist eine Alternative ...
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]);
}
DirectoryInfo Folder = new DirectoryInfo(Server.MapPath(path));
if (Folder .Exists)
{
foreach (FileInfo fl in Folder .GetFiles())
{
fl.Delete();
}
Folder .Delete();
}
Dies zeigt, wie wir den Ordner löschen und überprüfen, ob wir das Textfeld verwenden
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();
}
}
}
using System.IO;
string[] filePaths = Directory.GetFiles(@"c:\MyDir\");
foreach (string filePath in filePaths)
File.Delete(filePath);
Anruf von der Hauptleitung
static void Main(string[] args)
{
string Filepathe =<Your path>
DeleteDirectory(System.IO.Directory.GetParent(Filepathe).FullName);
}
Fügen Sie diese Methode hinzu
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);
}
}
Um den Ordner zu löschen, ist dies Code mithilfe eines Textfelds und einer Schaltfläche 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);
}
}
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
}
Directory.CreateDirectory
IO.Directory.Delete(HttpContext.Current.Server.MapPath(path), True)
Mehr brauchst du nicht