[英]How to delete all files/folders but keep the root folder in C#
我寫了一些代碼來遞歸刪除 .Net 中的所有文件/文件夾,它可以工作,但我想保留根文件夾。 有沒有辦法修改文件夾刪除條件 (Directory.GetFiles(sPath).Length == 0 && Directory.GetDirectories(sPath).Length == 0) 以知道它是根文件夾並且即使沒有文件也不刪除它/文件夾留在根目錄?
void CleanupFiles(String sPath, int iDayDelAge)
{
if (iDayDelAge != 0) // enabled?
{
// Check for aged files to remove
foreach (String file in Directory.GetFiles(sPath))
{
FileInfo fi = new FileInfo(file);
if (fi.LastWriteTime < DateTime.Now.AddDays(iDayDelAge * -1)) // overdue?
{
fi.Delete();
}
}
// Recursively search next subfolder if available
foreach (String subfolder in Directory.GetDirectories(sPath))
{
CleanupFiles(subfolder, iDayDelAge);
}
// Remove empty folder
if (Directory.GetFiles(sPath).Length == 0 && Directory.GetDirectories(sPath).Length == 0)
{
Directory.Delete(sPath);
}
}
}
稍微修改一下代碼。 添加一個新參數 root,並在遞歸調用中將其作為 false 傳遞。
static void Main(string[] args)
{
CleanupFiles(xxx, xxx, true);
}
void CleanupFiles(String sPath, int iDayDelAge, bool root)
{
if (iDayDelAge != 0) // enabled?
{
// Check for aged files to remove
foreach (String file in Directory.GetFiles(sPath))
{
FileInfo fi = new FileInfo(file);
if (fi.LastWriteTime < DateTime.Now.AddDays(iDayDelAge * -1)) // overdue?
{
fi.Delete();
}
}
// Recursively search next subfolder if available
foreach (String subfolder in Directory.GetDirectories(sPath))
{
CleanupFiles(subfolder, iDayDelAge, false);
}
// Remove empty folder
if (Directory.GetFiles(sPath).Length == 0 && Directory.GetDirectories(sPath).Length == 0 && !root)
{
Directory.Delete(sPath);
}
}
}
我不會亂用遞歸刪除。 並使用DirectoryInfo
類刪除目錄。
void CleanupFiles(String sPath, int iDayDelAge)
{
if (iDayDelAge == 0) // enabled?
{
return;
}
// Check for aged files to remove
foreach (String file in Directory.GetFiles(sPath))
{
FileInfo fi = new FileInfo(file);
if (fi.LastWriteTime < DateTime.Now.AddDays(iDayDelAge * -1)) // overdue?
{
fi.Delete();
}
}
foreach (String subfolder in Directory.GetDirectories(sPath))
{
var dirInfo = new DirectoryInfo(subfolder);
dirInfo.Delete(true);
}
}
您還可以依賴 Microsoft 提供的 API 而不是顯式遞歸:
foreach (var file in Directory.GetFiles(sPath))
{
File.Delete(file);
}
foreach (var directory in Directory.GetDirectories(sPath, "*", SearchOption.TopDirectoryOnly))
{
Directory.Delete(directory, true);
}
這應該首先刪除根目錄(spath)中的所有文件,然后遞歸刪除所有子目錄和內容。
這個例子應該像你描述的那樣工作。
public static void Main() {
var start = new DirectoryInfo( @"C:\Temp\Test" );
CleanupFiles( start, 5, true );
}
/// <summary>
/// <para>Remove any files last written to <paramref name="daysAgo"/> or before.</para>
/// <para>Then recursively removes any empty sub-folders, but not the starting folder (when <paramref name="isRootFolder"/> is true).</para>
/// <para>Attempts to remove any old read-only files also.</para>
/// </summary>
/// <param name="directory"></param>
/// <param name="daysAgo"></param>
/// <param name="isRootFolder"></param>
/// <param name="removeReadOnlyFiles"></param>
public static void CleanupFiles( [NotNull] DirectoryInfo directory, int daysAgo, Boolean isRootFolder, Boolean removeReadOnlyFiles = true ) {
if ( directory == null ) {
throw new ArgumentNullException( paramName: nameof( directory ) );
}
if ( daysAgo < 1 ) {
return;
}
directory.Refresh();
if ( !directory.Exists ) {
return;
}
var before = DateTime.UtcNow.AddDays( -daysAgo );
// Check for aged files to remove
Parallel.ForEach( directory.EnumerateFiles().AsParallel().Where( file => file.LastWriteTimeUtc <= before ), file => {
if ( file.IsReadOnly ) {
if ( removeReadOnlyFiles ) {
file.IsReadOnly = false;
}
else {
return;
}
}
file.Delete();
} );
foreach ( var subfolder in directory.EnumerateDirectories() ) {
CleanupFiles( subfolder, daysAgo, false, removeReadOnlyFiles );
}
if ( !isRootFolder ) {
if ( !directory.EnumerateDirectories().Any() && !directory.EnumerateFiles().Any() ) {
directory.Delete();
}
}
}
}
我想看看它的異步版本是如何工作的。 干得好。
public class Program {
public static async Task Main( String[] args ) {
await TestCleaningFolders.Test().ConfigureAwait(false);
}
}
public class TestCleaningFolders {
public static async Task Test() {
var start = new DirectoryInfo( @"T:\Temp\Test" );
var cancel = new CancellationTokenSource();
var olderThan = DateTime.UtcNow.AddDays( -5 );
var onException = new Action<Exception>( exception => Console.WriteLine( exception.ToString() ) ); //could easily be other logging or something..
await CleanupFilesAsync( start, olderThan, deleteEmptyFolders: true, removeReadOnlyFiles: true, onException: onException, token: cancel.Token )
.ConfigureAwait( false );
}
/// <summary>
/// <para>Remove any files last written to on or before <paramref name="olderThan" />.</para>
/// <para>Then recursively removes any empty sub-folders, but not the starting folder (when <paramref name="deleteEmptyFolders" /> is true).</para>
/// <para>Attempts to remove any old read-only files also.</para>
/// </summary>
/// <param name="folder"></param>
/// <param name="olderThan"></param>
/// <param name="deleteEmptyFolders"></param>
/// <param name="removeReadOnlyFiles"></param>
/// <param name="onException"></param>
/// <param name="token"></param>
[NotNull]
public static Task CleanupFilesAsync( [NotNull] DirectoryInfo folder, DateTime olderThan, Boolean deleteEmptyFolders, Boolean removeReadOnlyFiles,
[CanBeNull] Action<Exception> onException, CancellationToken token ) {
if ( folder is null ) {
throw new ArgumentNullException( nameof( folder ) );
}
return Task.Run( async () => {
folder.Refresh();
if ( folder.Exists ) {
if ( ScanAndRemoveOldFiles() ) {
await ScanIntoSubFolders().ConfigureAwait( false );
RemoveFolderIfEmpty();
}
}
}, token );
void Log<T>( T exception ) where T : Exception {
Debug.WriteLine( exception.ToString() );
if ( Debugger.IsAttached ) {
Debugger.Break();
}
onException?.Invoke( exception );
}
Boolean ScanAndRemoveOldFiles() {
try {
foreach ( var file in folder.EnumerateFiles().TakeWhile( info => !token.IsCancellationRequested ) ) {
RemoveFileIfOld( file );
if ( token.IsCancellationRequested ) {
return false; //Added another check because a delete operation itself can take time (where a cancel could be requested before the next findfile).
}
}
}
catch ( UnauthorizedAccessException exception ) {
Log( exception );
return false;
}
catch ( SecurityException exception ) {
Log( exception );
return false;
}
catch ( DirectoryNotFoundException exception ) {
Log( exception );
return false;
}
catch ( IOException exception ) {
Log( exception );
}
return true;
}
void RemoveFileIfOld( FileInfo fileInfo ) {
if ( fileInfo is null ) {
throw new ArgumentNullException( paramName: nameof( fileInfo ) );
}
try {
if ( !fileInfo.Exists || fileInfo.LastWriteTimeUtc > olderThan ) {
return;
}
if ( fileInfo.IsReadOnly ) {
if ( removeReadOnlyFiles ) {
fileInfo.IsReadOnly = false;
}
else {
return;
}
}
fileInfo.Delete();
}
catch ( FileNotFoundException exception ) {
Log( exception );
}
catch ( SecurityException exception ) {
Log( exception );
}
catch ( UnauthorizedAccessException exception ) {
Log( exception );
}
catch ( IOException exception ) {
Log( exception );
}
}
async Task ScanIntoSubFolders() {
try {
foreach ( var subfolder in folder.EnumerateDirectories().TakeWhile( info => !token.IsCancellationRequested ) ) {
await CleanupFilesAsync( subfolder, olderThan, deleteEmptyFolders: true, removeReadOnlyFiles: removeReadOnlyFiles, onException, token: token )
.ConfigureAwait( false );
}
}
catch ( DirectoryNotFoundException exception ) {
Log( exception );
}
catch ( SecurityException exception ) {
Log( exception );
}
catch ( UnauthorizedAccessException exception ) {
Log( exception );
}
catch ( IOException exception ) {
Log( exception );
}
}
void RemoveFolderIfEmpty() {
try {
if ( !deleteEmptyFolders || folder.EnumerateDirectories().Any() || folder.EnumerateFiles().Any() ) {
return;
}
folder.Delete();
}
catch ( FileNotFoundException exception ) {
Log( exception );
}
catch ( DirectoryNotFoundException exception ) {
Log( exception );
}
catch ( SecurityException exception ) {
Log( exception );
}
catch ( UnauthorizedAccessException exception ) {
Log( exception );
}
catch ( IOException exception ) {
Log( exception );
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.