It's search repeatedly in the folder - c#

Files and folders before the set date are deleted codes.
However, there is a problem.
I want to check the file and delete in the root folder and check the file and delete in the subfolder only once
but check the file in the root folder after delete the file in the subfolder.
I do not want to repeatedly check the file that I already confirmed.
public void FolderAndFileDelete(DirectoryInfo directoryInfo, SQLiteConnection connection, HashSet<string> splitedExtension, DateTime setTime)
{
FileInfo[] files = directoryInfo.GetFiles();
DirectoryInfo[] directoryInfos = directoryInfo.GetDirectories();
if (files != null)
{
foreach (var file in files)
{
file.Delete();
}
if (subFolderRemoveCheckBox.Checked == true)
{
foreach (DirectoryInfo subfolder in directoryInfos)
{
if (subfolder.GetFiles().Length == 0)
{
subfolder.Delete();
}
else if (subfolder.GetFiles().Length != 0)
{
this.FolderAndFileDelete(subfolder, connection, splitedExtension, setTime);
}
if (!subfolder.Exists)
return;
}
}
}
}
How can I fix it?

Your method can be reduced to something a little simpler, since you can pass true to the Delete method of a DirectoryInfo if you want it to remove all files and sub-directories. Note that I added a bool parameter to specify if sub-folders should be removed, so you would pass subFolderRemoveCheckBox.Checked for this argument:
public void DeleteContents(DirectoryInfo directoryInfo, bool includeSubFolders = false)
{
foreach (var file in directoryInfo.GetFiles())
{
file.Delete();
}
if (includeSubFolders)
{
foreach (var subDirectory in directoryInfo.GetDirectories())
{
subDirectory.Delete(true);
}
}
}

Related

C# - Count all Files in directory including Zip in Zip etc

I have a directory where all kind of random data is in it including ZIP archives which could also include ZIP archives itself and so on. What I want to count is all data except the ZIP archives.
My attempt with starting to count the data in the ZIP files:
static void Main(string[] args)
{
DirectoryInfo directoryInfo = new DirectoryInfo(#"C:\Temp");
int count = 0;
foreach (FileInfo file in directoryInfo.GetFiles())
{
if (file.Extension.Equals(".zip"))
{
count += ZipFileCount(file.FullName);
}
}
Console.WriteLine(count);
}
public static int ZipFileCount(String zipFileName)
{
using (ZipArchive archive = ZipFile.Open(zipFileName, ZipArchiveMode.Read))
{
foreach (var entry in archive.Entries)
{
if (!String.IsNullOrEmpty(entry.Name))
{
count += 1;
if (entry.Name.Substring(entry.Name.Length - 3).Equals("zip"))
{
ZipFileCount(entry.Name);
}
}
}
return count;
}
}
That didn't work out as ZipFileCount(entry.Name) does not provide the right entries in the ZIP of the ZIP.
Anybody can help me out to fix this?
One way of accomplishing it is extracting all the zips to a temporary folder recursively and then count for non-zip files inside of those directories. Once we get the count we can delete the intermediate files and revert the system to initial state. Remember the user needs to have write permissions on the file system to run the code in that particular directory.
using System;
using System.IO;
using System.IO.Compression;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
DirectoryInfo directoryInfo = new DirectoryInfo(#"C:\Temp");
ProcessDirectory(directoryInfo); // Process the directory and extract any zip files.
int count = 0;
foreach (DirectoryInfo subdirectory in directoryInfo.EnumerateDirectories())
{
if (subdirectory.Name.EndsWith(".ExtractedFiles")) // Count only extracted zip files in root directory.
{
count = CountFiles(subdirectory, count);
}
}
DeleteIntermediateFiles(directoryInfo); // Delete the extracted files.
Console.WriteLine(count);
}
public static void ProcessDirectory(DirectoryInfo directoryInfo)
{
foreach (DirectoryInfo subdirectory in directoryInfo.EnumerateDirectories())
{
ProcessDirectory(subdirectory); //Process subdirectories.
}
ProcessFiles(directoryInfo); //Process files.
}
private static void ProcessFiles(DirectoryInfo directoryInfo)
{
foreach (FileInfo file in directoryInfo.EnumerateFiles())
{
if (file.Extension.Equals(".zip")) // extract zip files.
{
var extractFilesDirectory = directoryInfo.CreateSubdirectory(
Path.GetFileNameWithoutExtension(file.Name) + ".ExtractedFiles");
ZipFile.ExtractToDirectory(file.FullName, extractFilesDirectory.FullName);
ProcessDirectory(extractFilesDirectory); //process extracted files.
}
}
}
public static int CountFiles(DirectoryInfo directoryInfo, int count)
{
foreach (DirectoryInfo subdirectory in directoryInfo.EnumerateDirectories())
{
count = CountFiles(subdirectory, count);
}
foreach (var fileInfo in directoryInfo.GetFiles())
{
if (fileInfo.Extension != ".zip") //exclude zip files while counting.
count++;
}
return count;
}
public static void DeleteIntermediateFiles(DirectoryInfo directoryInfo)
{
foreach (DirectoryInfo subdirectory in directoryInfo.EnumerateDirectories())
{
if (subdirectory.Name.EndsWith(".ExtractedFiles"))
{
Directory.Delete(subdirectory.FullName, true);
}
}
}
}
}

Proceed If File Doesn't Exist

I have the following code:
public static void readtext(string pathtoText)
{
if (File.Exists(pathtoText))
{
string[] lines = System.IO.File.ReadAllLines(pathtoText);
// Display the file contents by using a foreach loop.
foreach (string line in lines)
{
clearPath(line);
}
}
else
{
Console.WriteLine("{0} doesn't exist, or isn't a valid text file", pathtoText);
}
}
public static void clearPath(string path)
{
if(Directory.Exists(path))
{
int directoryCount = Directory.GetDirectories(path).Length;
if(directoryCount > 0)
{
Console.WriteLine("{0} has Subdirectories to Remove", path);
DirectoryInfo di = new DirectoryInfo(path);
foreach (DirectoryInfo dir in di.GetDirectories())
{
dir.Delete(true);
}
}
else
{
Console.WriteLine("{0} has no directories to remove", path);
}
int fileCount = Directory.GetFiles(path).Length;
if (fileCount > 0)
{
Console.WriteLine("{0} has files to Remove", path);
System.IO.DirectoryInfo di = new DirectoryInfo(path);
foreach (FileInfo file in di.GetFiles())
{
try
{
file.Delete();
}
catch(System.IO.IOException)
{
Console.WriteLine("Please Close the following File {0}", file.Name);
}
}
}
}
else
{
Console.WriteLine("Path Doesn't Exist {0}", path);
}
}
My function reads directories from a text file and passes it to clearPath which checks if the directory exists, and if so, cleans it. My problem is that, if a directory doesn't exist, it stops the program(it doesn't move to the next directory to check if it exists and clean, the for each loop just stops) .
How do I get it to the next directory even if specific directory doesn't exist?
it is possible that you have empty lines in your file?
you can try something like that:
foreach (string line in lines)
{
if (!String.IsNullOrWhiteSpace(line))
{
clearPath(line.trim());
}
}

Delete all files from a directory except for folder and it's contents

I am trying to remove all files on my storage card without removing one. I can keep the directory I specify but not its contents with my current code. It just leaves the blank
folder data because it removes everything inside. How can I keep it from removing that folder and its contents?
private void button1_Click(object sender, EventArgs e)
{
ScanDirectory scanDirectory = new ScanDirectory();
scanDirectory.WalkDirectory(#"/Storage Card");
scanDirectory.WalkDirectory(#"/Application");
}
public class ScanDirectory
{
public void WalkDirectory(string directory)
{
WalkDirectory(new DirectoryInfo(directory));
}
private static void WalkDirectory(DirectoryInfo directory)
{
// Scan all files in the current path
foreach (FileInfo file in directory.GetFiles())
{
file.Attributes &= ~FileAttributes.ReadOnly;
var name = file.Name;
name = name.ToLower();
if (name != "test.txt")
{
file.Delete();
}
}
DirectoryInfo[] subDirectories = directory.GetDirectories();
foreach (DirectoryInfo subDirectory in subDirectories)
{
WalkDirectory(subDirectory);
subDirectory.Attributes &= ~FileAttributes.ReadOnly;
var name = subDirectory.Name;
name = name.ToLower();
if (name != "data")
{
subDirectory.Delete();
}
}
}
}
The problem is the way in which the recursive function calls are done: the main function private static void WalkDirectory(DirectoryInfo directory) deletes all files and is called every time (even while analysing a subdirectory). Here you have a fix to make this code work as you wish:
private static void WalkDirectory(DirectoryInfo directory)
{
if (directory.Name.ToLower() != "data")
{
// Scan all files in the current path
foreach (FileInfo file in directory.GetFiles())
{
file.Attributes &= ~FileAttributes.ReadOnly;
var name = file.Name;
name = name.ToLower();
if (name != "test.txt")
{
file.Delete();
}
}
DirectoryInfo[] subDirectories = directory.GetDirectories();
foreach (DirectoryInfo subDirectory in subDirectories)
{
WalkDirectory(subDirectory);
subDirectory.Attributes &= ~FileAttributes.ReadOnly;
var name = subDirectory.Name;
name = name.ToLower();
if (name != "data")
{
subDirectory.Delete();
}
}
}
}
private static void WalkDirectory(DirectoryInfo directory)
{
if (directory.Name.ToLower() != "data")
{
// Scan all files in the current path
foreach (FileInfo file in directory.GetFiles())
{
file.Attributes &= ~FileAttributes.ReadOnly;
var name = file.Name;
name = name.ToLower();
if (name != "test.txt")
{
file.Delete();
}
}
DirectoryInfo[] subDirectories = directory.GetDirectories();
foreach (DirectoryInfo subDirectory in subDirectories)
{
WalkDirectory(subDirectory);
subDirectory.Attributes &= ~FileAttributes.ReadOnly;
var name = subDirectory.Name;
name = name.ToLower();
if (name != "data")
{
subDirectory.Delete();
}
}
}
}

Error In search in Root Drive like D:\

I write this code and work when I select any folder (with search option = SearchOption.AllDirectories ) but for
Drive Like D:\ I get error
" access to path D:\System Volume Information is denied"
and I add "\" to this path but still get error
if (dirListBox.Items.Count == 0)
{
foreach (int Index in disksListBox.CheckedIndices)
{
String Dir = disksListBox.Items[Index].ToString().Substring(0, 2);
Dir += #"\";
if (CheckExists(Dir))
{
Dirs.Add(Dir);
}
}
}
else
{
for (int Index = 0; Index < dirListBox.Items.Count; Index++)
{
String Dir = dirListBox.Items[Index].ToString();
Dirs.Add(Dir);
}
}
if (rdb_thisdir.Checked == true)
OptionDir = SearchOption.TopDirectoryOnly;
else
OptionDir = SearchOption.AllDirectories; // when search D:\ , Get Error But Work for Folder
if (rdbversion1.Checked == true)
{
ListViewItem lstitm = new ListViewItem();
foreach (String Dir in Dirs)
{
try
{
DirectoryInfo DirInfo = new DirectoryInfo(Dir);
FileInfo[] FileS = DirInfo.GetFiles(SearchPattern,OptionDir); //error when Dir="D:\\"
foreach (FileInfo file in FileS)
{
try
{
if (Check_Attributes(file) && Check_DateTime(file))
{
listFileFounded.Items.Add(file.FullName.ToString());
lstitm = lwfound.Items.Add(file.Extension.ToString());
lstitm.SubItems.Add(file.Name.ToString());
lstitm.SubItems.Add((file.Length / 1024).ToString());
lstitm.SubItems.Add(file.Attributes.ToString());
lstitm.SubItems.Add(file.FullName.ToString());
}
}
catch
{ }
}
}
catch ()
{
}
}
Your D: drive contains a folder "System Volume Information" that you don't have the privileges to access. So you will need to either not access it, or catch the exception and handle it to your liking. Not having access to a folder is not uncommon outside of ones own PC, so you might want to think about handling that scenario in your user interface. Maybe paint the folder in grey or display a lock icon or something.
There was a trick to do it. Do Enable Sharing to this folder.
For more information id here
Or do this trick .....
static void RecursiveGetFiles(string path)
{
DirectoryInfo dir = new DirectoryInfo(path);
try
{
foreach (FileInfo file in dir.GetFiles())
{
MessageBox.Show(file.FullName);
}
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("Access denied to folder: " + path);
}
foreach (DirectoryInfo lowerDir in dir.GetDirectories())
{
try
{
RecursiveGetFiles(lowerDir.FullName);
}
catch (UnauthorizedAccessException)
{
MessageBox.Show("Access denied to folder: " + path);
}
}
}
}
kamil Krasinsky answered it .. here

Forcefully Replacing Existing Files during Extracting File using System.IO.Compression?

I am using the following code to extract all files in a folder
using (ZipArchive archive = new ZipArchive(zipStream))
{
archive.ExtractToDirectory(location);
}
But if one file exist then it throws an exception. Is there is any way to tell the Compression API to replace the existing files.
I found one way is to get all the file names first then check whether file exist and delete it. But this is somehow very costly for me.
I have created an extension. any comment to it improve will be appreciated,
public static class ZipArchiveExtensions
{
public static void ExtractToDirectory(this ZipArchive archive, string destinationDirectoryName, bool overwrite)
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}
DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
string destinationDirectoryFullPath = di.FullName;
foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.GetFullPath(Path.Combine(destinationDirectoryFullPath, file.FullName));
if (!completeFileName.StartsWith(destinationDirectoryFullPath, StringComparison.OrdinalIgnoreCase))
{
throw new IOException("Trying to extract file outside of destination directory. See this link for more info: https://snyk.io/research/zip-slip-vulnerability");
}
if (file.Name == "")
{// Assuming Empty for Directory
Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
continue;
}
file.ExtractToFile(completeFileName, true);
}
}
}
This code will not throw exception when the folder is not exist, instead of that it will create the folder.
public static class ZipArchiveExtensions
{
public static void ExtractToDirectory(this ZipArchive archive, string destinationDirectoryName, bool overwrite)
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}
foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.Combine(destinationDirectoryName, file.FullName);
string directory = Path.GetDirectoryName(completeFileName);
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
if (file.Name != "")
file.ExtractToFile(completeFileName, true);
}
}
}
Take a look at this: Creating zip files easily in .NET 4.5. Your problem seems to be adressed. Alternatively, you can also check DotNetZip.
As I'm a total Linq fan, the Linq-ish way just for reference:
using (var strm = File.OpenRead(zipPath))
using (ZipArchive a = new ZipArchive(strm))
{
a.Entries.Where(o => o.Name == string.Empty && !Directory.Exists(Path.Combine(basePath, o.FullName))).ToList().ForEach(o => Directory.CreateDirectory(Path.Combine(basePath, o.FullName)));
a.Entries.Where(o => o.Name != string.Empty).ToList().ForEach(e => e.ExtractToFile(Path.Combine(basePath, e.FullName), true));
}
You can extract files to some temp directory and than copy files with the
"File.Copy" with the ovveride option true to your destination directory
I know that it's not a perfect solution , but this way you do not need to
check if file exist
Here is a method that takes a path to the zip file.
Based on the accepted answer.
public void ExtractZipFileToDirectory(string sourceZipFilePath, string destinationDirectoryName, bool overwrite)
{
using (var archive = ZipFile.Open(sourceZipFilePath, ZipArchiveMode.Read))
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}
DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
string destinationDirectoryFullPath = di.FullName;
foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.GetFullPath(Path.Combine(destinationDirectoryFullPath, file.FullName));
if (!completeFileName.StartsWith(destinationDirectoryFullPath, StringComparison.OrdinalIgnoreCase))
{
throw new IOException("Trying to extract file outside of destination directory. See this link for more info: https://snyk.io/research/zip-slip-vulnerability");
}
if (file.Name == "")
{// Assuming Empty for Directory
Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
continue;
}
file.ExtractToFile(completeFileName, true);
}
}
}
Since .NET Standard 2.1, it's as easy as setting overwriteFiles to true in:
ZipFile.ExtractToDirectory(string sourceFile, string destDir, Encoding entryNameEncoding, bool overwriteFiles)
Example:
ZipFile.ExtractToDirectory("c:\\file.zip","c:\\destination_folder", Encoding.UTF8, true);
Hi I'm using DotNetZip download from nugget.
I just simply use this code.
This will auto replace the files in the directory if exists.
"OverwriteSilently" !
using (ZipFile archive = new ZipFile(#"" + System.Environment.CurrentDirectory + "\\thezipfile.zip"))
{
archive.ExtractAll(#"" + System.Environment.CurrentDirectory, ExtractExistingFileAction.OverwriteSilently);
}
This is useful when you have zip file path
public static class ZipArchiveHelper
{
public static void ExtractToDirectory(string archiveFileName, string destinationDirectoryName, bool overwrite)
{
if (!overwrite)
{
ZipFile.ExtractToDirectory(archiveFileName, destinationDirectoryName);
}
else
{
using (var archive = ZipFile.OpenRead(archiveFileName))
{
foreach (var file in archive.Entries)
{
var completeFileName = Path.Combine(destinationDirectoryName, file.FullName);
var directory = Path.GetDirectoryName(completeFileName);
if (!Directory.Exists(directory) && !string.IsNullOrEmpty(directory))
Directory.CreateDirectory(directory);
if (file.Name != "")
file.ExtractToFile(completeFileName, true);
}
}
}
}
}
A little remade method from the answer to create all the folders
public static void ExtractToDirectory(this ZipArchive archive, string destinationDirectoryName, bool overwrite)
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}
foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.Combine(destinationDirectoryName, file.FullName);
if (file.Name == "")
{// Assuming Empty for Directory
Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
continue;
}
// create dirs
var dirToCreate = destinationDirectoryName;
for (var i = 0; i < file.FullName.Split('/').Length - 1; i++)
{
var s = file.FullName.Split('/')[i];
dirToCreate = Path.Combine(dirToCreate, s);
if (!Directory.Exists(dirToCreate))
Directory.CreateDirectory(dirToCreate);
}
file.ExtractToFile(completeFileName, true);
}
}
Looks like the only way to dodge including that blob of code is to simply delete the files before extracting the archive with del:
del (location + "\*")
using (ZipArchive archive = new ZipArchive(zipStream))
{
archive.ExtractToDirectory(location);
}
It's not exactly what the OP wanted, but it is compact.

Categories