Як за допомогою C # можна видалити всі файли та папки з каталогу, але все ж зберігати кореневий каталог?
Як за допомогою C # можна видалити всі файли та папки з каталогу, але все ж зберігати кореневий каталог?
Відповіді:
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()та GetDirectories().
Directory.Delete(path, true)подбає про всіх :)
file.Delete().
Так, це правильний спосіб зробити це. Якщо ви хочете дати собі "Очистити" (або, як я вважаю за краще, це функція "Порожня"), ви можете створити метод розширення.
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();
Emptyіснує вже в C #, для string. Якби я побачив щось інше на ім'я, Emptyя був би здивований, якби він змінив об'єкт (або файлову систему) замість того, щоб дати мені boolте, що говорить, чи воно порожнє чи ні. Через це я пішов би з прізвищем Clean.
Is(тобто IsEmptyзамість Empty).
Наступний код очистить папку рекурсивно:
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кине, якщо каталог не існує, тому було б безпечніше Directory.Existsспочатку перевірити.
Directory.Existsнедостатньо; після перевірки інший потік, можливо, перейменував або видалив каталог. Це безпечніше try-catch.
Directory.Createоскільки рекурсивна Directory.Delete, на жаль, не гарантується синхронністю ..
Ми також можемо проявити любов до 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);
}
}
}
foreach (var dir in info.GetDirectories("*", SearchOption.AllDirectories).OrderByDescending(dir => dir.FullName.Length)) dir.Delete();може бути корисним.
directory.EnumerateFiles()та directory.EnumerateDirectories()замість directory.Get*()методів.
IEnumerable<T>.ForEach()розширення містить стислий коментар XML "Порушення! Порушення! Нечисті!".
Найпростіший спосіб:
Directory.Delete(path,true);
Directory.CreateDirectory(path);
Майте на увазі, що це може видалити деякі дозволи в папці.
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)
Кожен метод, який я спробував, в якийсь момент з помилками 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);
Ось інструмент, яким я закінчив, прочитавши всі пости. Це робить
Це стосується
Він не використовує 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;
}
Наступний код очистить каталог, але залишить там кореневий каталог (рекурсивний).
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);
я використав
Directory.GetFiles(picturePath).ToList().ForEach(File.Delete);
для видалення старої картинки, і мені не потрібен жоден об’єкт у цій папці
Використання лише статичних методів у файлі та каталозі замість FileInfo та DirectoryInfo буде працювати швидше. (див. прийняту відповідь у розділі Яка різниця між File та FileInfo у C #? ). Відповідь показано як корисний метод.
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);
Якщо в Windows 7 ви тільки що створили його вручну за допомогою Провідника Windows, структура каталогу схожа на цю:
C:
\AAA
\BBB
\CCC
\DDD
І запустивши код, запропонований в оригінальному питанні, щоб очистити каталог C: \ AAA, рядок di.Delete(true)завжди виходить з ладу з IOException "Каталог не порожній" при спробі видалити BBB. Це, мабуть, через якусь затримку / кешування в Провіднику 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);
}
}
Ця версія не використовує рекурсивних дзвінків і вирішує проблему, що читається тільки.
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();
}
}
Наступний приклад показує, як ви можете це зробити. Спочатку створюється деякі каталоги та файл, а потім видаляється через 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 .
Це не найкращий спосіб вирішити це питання вище. Але це альтернатива ...
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();
}
це покаже, як ми видаляємо папку і перевіряємо її, ми використовуємо поле Text
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);
Дзвінок з основного
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);
}
}
Щоб видалити папку, це код за допомогою текстового поля та кнопки 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)
Вам не потрібно більше цього