Ce qui serait bien si DirectoryInfo avait une méthode comme .Clean ();
JL.
6
ou .DeleteFolders et DeleteFiles.
JL.
18
Vous devez savoir que vos suppressions peuvent très facilement lever une exception si un fichier est verrouillé (ou si vous n'avez pas de droits). Voir FileInfo.Delete pour une liste des exceptions.
Shane Courtrille
Réponses:
834
System.IO.DirectoryInfo di =newDirectoryInfo("YourPath");foreach(FileInfo file in di.GetFiles()){
file.Delete();}foreach(DirectoryInfo dir in di.GetDirectories()){
dir.Delete(true);}
Si votre répertoire peut contenir de nombreux fichiers, il EnumerateFiles()est plus efficace que cela GetFiles(), car lorsque vous l'utilisez, EnumerateFiles()vous pouvez commencer à l'énumérer avant que la collection entière ne soit retournée, par opposition à l' GetFiles()endroit où vous devez charger la collection entière en mémoire avant de commencer à l'énumérer. Voir cette citation ici :
Par conséquent, lorsque vous travaillez avec de nombreux fichiers et répertoires, EnumerateFiles () peut être plus efficace.
Il en va de même pour EnumerateDirectories()et GetDirectories(). Le code serait donc:
foreach(FileInfo file in di.EnumerateFiles()){
file.Delete();}foreach(DirectoryInfo dir in di.EnumerateDirectories()){
dir.Delete(true);}
Aux fins de cette question, il n'y a vraiment aucune raison d'utiliser GetFiles()et GetDirectories().
Qu'est-ce qui concerne stackoverflow.com/questions/12415105/… "Lorsque vous appelez Directory.Delete et qu'un fichier est ouvert de cette manière, Directory.Delete réussit à supprimer tous les fichiers mais lorsque Directory.Delete appelle RemoveDirectory un" répertoire n'est pas vide " une exception est levée car il existe un fichier marqué pour suppression mais pas réellement supprimé. "
Kiquenet
74
DirectoryInfo est lent car il rassemble beaucoup plus de données. BTW: Directory.Delete(path, true)s'occupera de tout :)
AcidJunkie
57
@AcidJunkie, Cela supprimera également le répertoire en question, tandis que l'OP demande spécifiquement que le répertoire racine soit conservé.
Marc L.
5
Notez que cela ne fonctionnera pas si l'un des fichiers est en lecture seule. Vous devez supprimer l'indicateur de lecture seule avant d'appeler file.Delete().
Ben
8
Cela semble ne pas fonctionner si les sous-répertoires contiennent des fichiers.
cdiggins
174
Oui, c'est la bonne façon de procéder. Si vous cherchez à vous donner une fonction "Clean" (ou, comme je préfère l'appeler, "Empty"), vous pouvez créer une méthode d'extension.
publicstaticvoidEmpty(thisSystem.IO.DirectoryInfo directory){foreach(System.IO.FileInfo file in directory.GetFiles()) file.Delete();foreach(System.IO.DirectoryInfo subDirectory in directory.GetDirectories()) subDirectory.Delete(true);}
Cela vous permettra ensuite de faire quelque chose comme ..
La dernière ligne doit être subDirectory.Delete (true) au lieu de directory.Delete (true). Je viens de couper et coller le code et il a supprimé le répertoire principal lui-même. Merci pour le code c'est super!
Aximili
26
notez qu'il Emptyexiste déjà en C #, pour string. Si je voyais quelque chose d'autre nommé Emptyje serais surpris s'il modifiait l'objet (ou le système de fichiers) au lieu de me donner un boolqui dit s'il est vide ou non. Pour cette raison, j'irais avec le nom Clean.
Par défaut
5
@Default: Je ne pense pas que le fait qu'un type ait déjà une propriété devrait avoir une incidence sur la question de savoir si un autre type (complètement indépendant) devrait l'avoir; et la convention pour les propriétés et les fonctions qui indiquent l'état des mots qui peuvent également être des verbes est de les préfixer Is(c'est-à-dire IsEmptyplutôt que Empty).
Adam Robinson
3
@AdamRobinson Je voulais juste en prendre note. Pour moi , ce que Microsoft a dans son code a une certaine incidence. Mais c'est à tout le monde d'interpréter :)
Par défaut
4
@simonhaines: Le but de la question était de vider le répertoire (c'est-à-dire de supprimer tout ce qu'il contient ), pas de supprimer le répertoire lui-même.
Adam Robinson
77
Le code suivant effacera le dossier récursivement:
privatevoid clearFolder(stringFolderName){DirectoryInfo dir =newDirectoryInfo(FolderName);foreach(FileInfo fi in dir.GetFiles()){
fi.Delete();}foreach(DirectoryInfo di in dir.GetDirectories()){
clearFolder(di.FullName);
di.Delete();}}
La deuxième option, Directory.Delete (String, Boolean) a fonctionné pour moi.
Stephen MacDougall
15
Cela supprime le répertoire racine, où l'OP a spécifiquement demandé qu'il soit conservé.
Marc L.
2
Deletejettera si le répertoire n'existe pas, il serait donc plus sûr de faire une Directory.Existsvérification en premier.
James
1
@James Directory.Existsn'est pas suffisant; après la vérification, un autre thread peut avoir renommé ou supprimé le répertoire. C'est plus sûr try-catch.
andre_ss6
2
@Marv Attention à simplement ajouter un Directory.Createcar le récursif Directory.Deleten'est malheureusement pas garanti d'être synchrone ..
Andrew Hanlon
38
Nous pouvons également montrer notre amour pour 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));
Notez que ma solution ici n'est pas performante, car j'utilise Get*().ToList().ForEach(...)ce qui génère le même IEnumerabledeux fois. J'utilise une méthode d'extension pour éviter ce problème:
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));
Voici la méthode d'extension:
/// <summary>/// Extensions for <see cref="System.Collections.Generic.IEnumerable"/>./// </summary>publicstaticclassIEnumerableOfTExtensions{/// <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>publicstaticvoidForEachInEnumerable<TEnumerable>(thisIEnumerable<TEnumerable> enumerable,Action<TEnumerable> action){foreach(var item in enumerable){
action(item);}}}
Et si vous essayez également de supprimer des sous-répertoires, cela foreach (var dir in info.GetDirectories("*", SearchOption.AllDirectories).OrderByDescending(dir => dir.FullName.Length)) dir.Delete();pourrait être utile.
Warty
1
Si vous aimez les performances, pensez à utiliser directory.EnumerateFiles()et directory.EnumerateDirectories()au lieu des directory.Get*()méthodes.
Tinister
1
Drôle, ma propre IEnumerable<T>.ForEach()extension a un commentaire XML résumé, "Violation! Violation! Impur!".
Marc L.
Hé quelle est la 2ème raison? Le 3ème? Etc.?
Bill Roberts
lol @RASX - il vous parle: "Si vous n'êtes pas d'accord avec ces objections philosophiques et que vous trouvez une valeur pratique dans ce modèle, allez-y et écrivez vous-même cette ligne triviale."
sachez que cela supprimera toutes les autorisations spéciales du chemin d'accès
Matthew Lock
6
Vous devez ajouter un délai d'attente entre ces deux actions. essayez d'exécuter ce code et vous obtiendrez Exception: while (true) {Directory.Delete (@ "C: \ Myfolder", true); Directory.CreateDirectory (@ "C: \ Myfolder"); }
RcMan
31
privatevoidClearFolder(stringFolderName){DirectoryInfo dir =newDirectoryInfo(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}}
Si vous savez qu'il n'y a pas de sous-dossiers, quelque chose comme ça peut être le plus simple:
J'ai utilisé cette fonction pour effacer le dossier temporaire du système. J'ai juste ajouté try-catch autour de Delete () et IsReadOnly pour ignorer toutes les exceptions, et cela a fonctionné.
humbads
@humbads, pouvez-vous mettre à jour cette réponse, ou mettre le code ici, et je mettrai à jour vos modifications?
comme ci-dessus: sachez que cela supprimera toutes les autorisations spéciales du chemin.
hB0
8
Toutes les méthodes que j'ai essayées ont échoué à un moment donné avec des erreurs System.IO. La méthode suivante fonctionne à coup sûr, même si le dossier est vide ou non, en lecture seule ou non, etc.
Je préfère toujours rd / s / q + mkdir pour vider les répertoires.
Dawid Ohia
7
Ce n'est pas une solution multiplateforme. Les systèmes de type Unix n'ont clairement pas cmd.exe, ils n'exécutent même pas de fichiers .exe. C # n'est pas seulement Windows, il y a aussi Mono, qui est multi-plateforme.
Nom d'affichage
1
@SargeBorsch, il n'y avait aucune exigence multiplateforme dans la question et étant C #, il est très probable que la solution sera utilisée pour Windows. Il semble que ce soit la seule réponse qui n'utilise pas les fonctions .NET, c'est donc très utile comme alternative.
Alex Pandrea
7
Voici l'outil avec lequel j'ai terminé après avoir lu tous les articles. Cela fait
Supprime tout ce qui peut être supprimé
Renvoie false si certains fichiers restent dans le dossier
Ça parle de
Fichiers en lecture seule
Délai de suppression
Fichiers verrouillés
Il n'utilise pas Directory.Delete car le processus est abandonné à l'exception.
/// <summary>/// Attempt to empty the folder. Return false if it fails (locked files...)./// </summary>/// <param name="pathName"></param>/// <returns>true on success</returns>publicstaticboolEmptyFolder(string pathName){bool errors =false;DirectoryInfo dir =newDirectoryInfo(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;}
Le code suivant nettoiera le répertoire, mais y laissera le répertoire racine (récursif).
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);
L'utilisation de méthodes statiques avec File and Directory au lieu de FileInfo et DirectoryInfo fonctionnera plus rapidement. (voir la réponse acceptée à Quelle est la différence entre File et FileInfo en C #? ). Réponse affichée comme méthode d'utilité.
privatevoidClearFolder(stringFolderName){DirectoryInfo dir =newDirectoryInfo(FolderName);foreach(FileInfo fi in dir.GetFiles()){
fi.IsReadOnly=false;
fi.Delete();}foreach(DirectoryInfo di in dir.GetDirectories()){ClearFolder(di.FullName);
di.Delete();}}
Une exception de type «System.IO.IOException» s'est produite dans mscorlib.dll mais n'a pas été gérée dans le code utilisateur Informations supplémentaires: le répertoire n'est pas vide.
kipusoep
3
Dans Windows 7, si vous venez de le créer manuellement avec l'Explorateur Windows, la structure du répertoire est similaire à celle-ci:
C:
\AAA
\BBB
\CCC
\DDD
Et en exécutant le code suggéré dans la question d'origine pour nettoyer le répertoire C: \ AAA, la ligne di.Delete(true)échoue toujours avec IOException "Le répertoire n'est pas vide" lorsque vous essayez de supprimer BBB. C'est probablement à cause d'une sorte de retard / mise en cache dans l'Explorateur Windows.
Le code suivant fonctionne de manière fiable pour moi:
staticvoidMain(string[] args){DirectoryInfo di =newDirectoryInfo(@"c:\aaa");CleanDirectory(di);}privatestaticvoidCleanDirectory(DirectoryInfo di){if(di ==null)return;foreach(FileSystemInfo fsEntry in di.GetFileSystemInfos()){CleanDirectory(fsEntry asDirectoryInfo);
fsEntry.Delete();}WaitForDirectoryToBecomeEmpty(di);}privatestaticvoidWaitForDirectoryToBecomeEmpty(DirectoryInfo di){for(int i =0; i <5; i++){if(di.GetFileSystemInfos().Length==0)return;Console.WriteLine(di.FullName+ i);Thread.Sleep(50* i);}}
Qu'est-ce qui concerne stackoverflow.com/questions/12415105/… "Lorsque vous appelez Directory.Delete et qu'un fichier est ouvert de cette manière, Directory.Delete réussit à supprimer tous les fichiers mais lorsque Directory.Delete appelle RemoveDirectory un" répertoire n'est pas vide " une exception est levée car il existe un fichier marqué pour suppression mais pas réellement supprimé. "
Kiquenet
@Kiquenet: On dirait que nous avons trouvé un problème dans Windows. Windows aurait pu consulter la liste des fichiers marqués pour suppression et si tous les fichiers du répertoire sont marqués pour suppression, ne dites pas que le répertoire n'est pas vide. Quoi qu'il en soit, mon WaitForDirectoryToBecomeEmpty () est une solution de contournement.
farfareast
2
Cette version n'utilise pas d'appels récursifs et résout le problème en lecture seule.
publicstaticvoidEmptyDirectory(string directory){// First delete all the files, making sure they are not readonlyvar stackA =newStack<DirectoryInfo>();
stackA.Push(newDirectoryInfo(directory));var stackB =newStack<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 firstwhile(stackB.Any()){
stackB.Pop().Delete();}}
Ce n'est pas la meilleure façon de traiter le problème ci-dessus. Mais c'est une alternative ...
while(Directory.GetDirectories(dirpath).Length>0){//Delete all files in directorywhile(Directory.GetFiles(Directory.GetDirectories(dirpath)[0]).Length>0){File.Delete(Directory.GetFiles(dirpath)[0]);}Directory.Delete(Directory.GetDirectories(dirpath)[0]);}
Pourriez-vous être plus précis et expliquer comment et pourquoi cela devrait fonctionner?
Deep Frozen
3
Les réponses avec un seul code ne conviennent pas. Vous devez expliquer comment et pourquoi cela devrait fonctionner / résoudre le problème.
rdurand
0
cela montrera comment nous supprimons le dossier et le vérifions, nous utilisons la zone de texte
using System.IO;
namespace delete_the_folder
{publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}privatevoidDeletebt_Click(object sender,EventArgs e){//the first you should write the folder placeif(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");elseMessageBox.Show("Its a file");string path =Pathfolder.Text;FileInfo myfileinf =newFileInfo(path);
myfileinf.Delete();}}}
publicstaticvoidDeleteDirectory(string path){if(Directory.Exists(path)){//Delete all files from the Directoryforeach(string file inDirectory.GetFiles(path)){File.Delete(file);}//Delete all child Directoriesforeach(string directory inDirectory.GetDirectories(path)){DeleteDirectory(directory);}//Delete a DirectoryDirectory.Delete(path);}}
Pour supprimer le dossier, voici le code à l'aide de la zone de texte et d'un bouton using System.IO;:
privatevoidDeletebt_Click(object sender,EventArgs e){System.IO.DirectoryInfo myDirInfo =newDirectoryInfo(@""+delete.Text);foreach(FileInfo file in myDirInfo.GetFiles()){
file.Delete();}foreach(DirectoryInfo dir in myDirInfo.GetDirectories()){
dir.Delete(true);}}
Voir ci-dessous ... "supprimer et recréer" n'est pas la même chose que conserver, toutes les personnalisations ACL seront perdues.
Marc L.
J'ai essayé quelque chose de très similaire à cela depuis que je ne me souciais pas des personnalisations ACL et que je rencontrais des problèmes avec le dossier qui n'était pas créé aprèsDirectory.CreateDirectory
JG dans SD
-3
La seule chose que vous devez faire est de mettre optional recursive parameterà True.
Réponses:
Si votre répertoire peut contenir de nombreux fichiers, il
EnumerateFiles()
est plus efficace que celaGetFiles()
, car lorsque vous l'utilisez,EnumerateFiles()
vous pouvez commencer à l'énumérer avant que la collection entière ne soit retournée, par opposition à l'GetFiles()
endroit où vous devez charger la collection entière en mémoire avant de commencer à l'énumérer. Voir cette citation ici :Il en va de même pour
EnumerateDirectories()
etGetDirectories()
. Le code serait donc:Aux fins de cette question, il n'y a vraiment aucune raison d'utiliser
GetFiles()
etGetDirectories()
.la source
Directory.Delete(path, true)
s'occupera de tout :)file.Delete()
.Oui, c'est la bonne façon de procéder. Si vous cherchez à vous donner une fonction "Clean" (ou, comme je préfère l'appeler, "Empty"), vous pouvez créer une méthode d'extension.
Cela vous permettra ensuite de faire quelque chose comme ..
la source
Empty
existe déjà en C #, pourstring
. Si je voyais quelque chose d'autre nomméEmpty
je serais surpris s'il modifiait l'objet (ou le système de fichiers) au lieu de me donner unbool
qui dit s'il est vide ou non. Pour cette raison, j'irais avec le nomClean
.Is
(c'est-à-direIsEmpty
plutôt queEmpty
).Le code suivant effacera le dossier récursivement:
la source
la source
Delete
jettera si le répertoire n'existe pas, il serait donc plus sûr de faire uneDirectory.Exists
vérification en premier.Directory.Exists
n'est pas suffisant; après la vérification, un autre thread peut avoir renommé ou supprimé le répertoire. C'est plus sûrtry-catch
.Directory.Create
car le récursifDirectory.Delete
n'est malheureusement pas garanti d'être synchrone ..Nous pouvons également montrer notre amour pour LINQ :
Notez que ma solution ici n'est pas performante, car j'utilise
Get*().ToList().ForEach(...)
ce qui génère le mêmeIEnumerable
deux fois. J'utilise une méthode d'extension pour éviter ce problème:Voici la méthode d'extension:
la source
foreach (var dir in info.GetDirectories("*", SearchOption.AllDirectories).OrderByDescending(dir => dir.FullName.Length)) dir.Delete();
pourrait être utile.directory.EnumerateFiles()
etdirectory.EnumerateDirectories()
au lieu desdirectory.Get*()
méthodes.IEnumerable<T>.ForEach()
extension a un commentaire XML résumé, "Violation! Violation! Impur!".La manière la plus simple:
N'oubliez pas que cela peut effacer certaines autorisations sur le dossier.
la source
Si vous savez qu'il n'y a pas de sous-dossiers, quelque chose comme ça peut être le plus simple:
la source
la source
Toutes les méthodes que j'ai essayées ont échoué à un moment donné avec des erreurs System.IO. La méthode suivante fonctionne à coup sûr, même si le dossier est vide ou non, en lecture seule ou non, etc.
la source
Voici l'outil avec lequel j'ai terminé après avoir lu tous les articles. Cela fait
Ça parle de
Il n'utilise pas Directory.Delete car le processus est abandonné à l'exception.
la source
Le code suivant nettoiera le répertoire, mais y laissera le répertoire racine (récursif).
la source
j'ai utilisé
pour supprimer la vieille photo et je n'ai besoin d'aucun objet dans ce dossier
la source
L'utilisation de méthodes statiques avec File and Directory au lieu de FileInfo et DirectoryInfo fonctionnera plus rapidement. (voir la réponse acceptée à Quelle est la différence entre File et FileInfo en C #? ). Réponse affichée comme méthode d'utilité.
la source
la source
la source
Dans Windows 7, si vous venez de le créer manuellement avec l'Explorateur Windows, la structure du répertoire est similaire à celle-ci:
Et en exécutant le code suggéré dans la question d'origine pour nettoyer le répertoire C: \ AAA, la ligne
di.Delete(true)
échoue toujours avec IOException "Le répertoire n'est pas vide" lorsque vous essayez de supprimer BBB. C'est probablement à cause d'une sorte de retard / mise en cache dans l'Explorateur Windows.Le code suivant fonctionne de manière fiable pour moi:
la source
Cette version n'utilise pas d'appels récursifs et résout le problème en lecture seule.
la source
utilisez la méthode GetDirectories de DirectoryInfo.
la source
L'exemple suivant montre comment procéder. Il crée d'abord des répertoires et un fichier, puis les supprime via
Directory.Delete(topPath, true);
:Il est extrait de https://msdn.microsoft.com/en-us/library/fxeahc5f(v=vs.110).aspx .
la source
Ce n'est pas la meilleure façon de traiter le problème ci-dessus. Mais c'est une alternative ...
la source
la source
cela montrera comment nous supprimons le dossier et le vérifions, nous utilisons la zone de texte
la source
la source
Appel du principal
Ajoutez cette méthode
la source
la source
Pour supprimer le dossier, voici le code à l'aide de la zone de texte et d'un bouton
using System.IO;
:la source
la source
Directory.CreateDirectory
La seule chose que vous devez faire est de mettre
optional recursive parameter
àTrue
.Directory.Delete("C:\MyDummyDirectory", True)
Merci à .NET. :)
la source
Tu n'as pas besoin de plus que ça
la source