C# How to select specific subdirectory - c#

im doing something similar to the cmd tree. And what im planning to check first C:\ than check the first folder in it if the first folder contains something in it go check it and so on until i get DirectoryNotFoundException. If i get such i want to skip the first folder and check the second one how to do that ?
static string path = #"C:\";
static void Main()
{
try
{
DirectoryInfo di = new DirectoryInfo(path);
DirectoryInfo[] fileNames = di.GetDirectories();
}
catch (DirectoryNotFoundException)
{
DirectoryInfo di = new DirectoryInfo(path);
DirectoryInfo[] fileNames = di.GetDirectories();
//i need to edit the picking of filenames.Something like PickSecond/Next
}
Console.ReadKey();
}

If you want to print the directory tree you can use recursion without getting any DirectoryNotFoundException. The following code will print to the console all the sub-directories starting from a specific path. The recursion works this way: every time a folder is found, if it's not empty then go to explore its sub-directories, otherwise go and check the next folder.
static void DirectoryTree(string directory, string indent = "")
{
try
{
DirectoryInfo currentDirectory = new DirectoryInfo(directory);
DirectoryInfo[] subDirectories = currentDirectory.GetDirectories();
// Print all the sub-directories in a recursive way.
for (int n = 0; n < subDirectories.Length; ++n)
{
// The last sub-directory is drawn differently.
if (n == subDirectories.Length - 1)
{
Console.WriteLine(indent + "└───" + subDirectories[n].Name);
DirectoryTree(subDirectories[n].FullName, indent + " ");
}
else
{
Console.WriteLine(indent + "├───" + subDirectories[n].Name);
DirectoryTree(subDirectories[n].FullName, indent + "│ ");
}
}
}
catch (Exception e)
{
// Here you could probably get an "Access Denied" exception,
// that's very likely if you are exploring the C:\ folder.
Console.WriteLine(e.Message);
}
}
static void Main()
{
// Consider exploring a more specific folder. If you just type "C:\"
// you are requesting to view all the folders in your computer.
var path = #"C:\SomeFolder" ;
Console.WriteLine(path);
if(Directory.Exists(path))
DirectoryTree(path);
else
Console.WriteLine("Invalid Directory");
Console.ReadKey();
}

Related

How to copy specific folder to new folder by clicking a button

One Question about coding (Visual Studio C# Windows form Application) There have Two folder: (Source and Target) and I build 1 button "Copy". In (Source) folder have random folders such "20190401", "20190402", "20190403", "20180401", "20170401" and "20160401". Every these folders have [10] ".txt" files. What is the coding if I only want to copy all "201904**" folders with [3] ".txt" files inside to "Target" folder?
Here my code for now, after I click a button the folder wouldn't copy. I guess there have some problem with this codes and I still not found it until. Hope you guys can help me, thank you.
*namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string FROM_DIR = "C:/Users/Desktop/Source/";
string TO_DIR = "C:/Users/Desktop/Target/";
DirectoryInfo diCopyForm = new DirectoryInfo(FROM_DIR);
DirectoryInfo[] fiDiskfiles = diCopyForm.GetDirectories();
string directname = "201904";
string filename = ".txt";
foreach (DirectoryInfo newfile in fiDiskfiles)
{
try
{
if (newfile.Name == "2019")
{
foreach (DirectoryInfo direc in newfile.GetDirectories())
if (direc.Name.StartsWith(directname))
{
int count = 0;
foreach (FileInfo file in direc.GetFiles())
{
if (file.Name.EndsWith(filename))
{
count++;
}
}
if (count == 3)
{
DirectoryCopy(direc.FullName,Path.Combine(TO_DIR,direc.Name), true);
count = 0;
MessageBox.Show("success");
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
{
// Get the subdirectories for the specified directory.
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
if (!dir.Exists)
{
throw new DirectoryNotFoundException("Source directory does not exist or could not be found: "+ sourceDirName);
}
DirectoryInfo[] dirs = dir.GetDirectories();
// If the destination directory doesn't exist, create it.
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
// Get the files in the directory and copy them to the new location.
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
string temppath = Path.Combine(destDirName, file.Name);
file.CopyTo(temppath, false);
}
// If copying subdirectories, copy them and their contents to new location.
if (copySubDirs)
{
foreach (DirectoryInfo subdir in dirs)
{
string temppath = Path.Combine(destDirName, subdir.Name);
DirectoryCopy(subdir.FullName, temppath, copySubDirs);
}
}
}
}
*}
By clicking the button, automatically copy all "201904**" folder and 3 ".txt files in (Source) folder to (target folder).
You didn't say which 3 txt files you want to copy so the code below copies all txt files, please explain how you select the files and I'll edit the code.
const string Source = #"C:\Users\Desktop\Source\";
const string Target = #"C:\Users\Desktop\Target\";
const string StartsWith = "201904";
const string FileType = "txt";
public static void Copy()
{
if (!Directory.Exists(Source)) //Check if the source directory exists
throw new Exception("Source directory is missing!");
Directory.CreateDirectory(Target); //If the target directory doesn't exists it will create one
var Directories = Directory.GetDirectories(Source, $"{StartsWith}*"); //Get directories which match the search pattern
for (int i = 0; i < Directories.Length; i++)
{
DirectoryInfo directory = new DirectoryInfo(Directories[i]);
Directory.CreateDirectory($"{Target}{directory.Name}"); //Create the directory in the target folder
var Files = Directory.GetFiles($"{Source}{directory.Name}", $"*.{FileType}"); //Get files
for (int j = 0; j < Files.Length; j++)
{
FileInfo file = new FileInfo(Files[j]);
File.Copy($"{Source}{directory.Name}" + #"\" + file.Name, $"{Target}{directory.Name}" + #"\" + file.Name); //Copy the file to the target folder
}
}
}
This code selects all directories which start with "201904" and all txt files inside them and copies it to the target folder.
EDIT: Fixed a mistake in the code

Access to the directory denied in C# - Console Application

I am trying to access the Documents directory and sub-directories, but every time it says access denied. I see the Exception:
System.UnauthorizedAccessException: Access to the path 'C:\Users\MyUser\Documents\My Music' is denied
Here is my code - all I am trying to do is get the total size of this directory.
class Program
{
static void Main(string[] args)
{
try {
// Make a reference to a directory.
string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
DirectoryInfo di = new DirectoryInfo(path);
// Get a reference to each file in that directory.
FileInfo[] fiArr = di.GetFiles(".", SearchOption.AllDirectories);
// Display the names and sizes of the files.
Console.WriteLine("The directory {0} contains the following files:", di.Name);
long size = 0;
foreach (FileInfo f in fiArr)
{
size += f.Length;
size++;
}
Console.WriteLine("The size of desktop files." + size);
}
catch(Exception e)
{
Console.WriteLine("Exceptions {0}" , e);
}
}
}
From what I can gather from skimming this thread it could be that these folders are soft links provided for Windows backward compatibility.
For resolving the coding problem, you could make your own recursive folder search that ignores the exceptions thrown when the current user does not have access to a given folder.
Something like this perhaps:
static IEnumerable<FileInfo> GetAllFilesRecursive(string path)
{
var di = new DirectoryInfo(path);
var files = new List<FileInfo>();
files.AddRange(di.GetFiles("."));
foreach (var directory in Directory.GetDirectories(path))
{
try
{
files.AddRange(GetAllFilesRecursive(directory));
}
catch (UnauthorizedAccessException) // ignore directories which the user does not have access to
{}
}
return files;
}
Then rewrite your code to use the new function:
static void Main(string[] args)
{
try
{
// Make a reference to a directory.
string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var fiArr = GetAllFilesRecursive(path);
// Display the names and sizes of the files.
Console.WriteLine("The directory {0} contains the following files:", path);
long size = 0;
foreach (FileInfo f in fiArr)
{
size += f.Length;
size++;
}
Console.WriteLine("The size of desktop files." + size);
}
catch (Exception e)
{
Console.WriteLine("Exceptions {0}", e);
}
}
The search should be on TopDirectoryOnly and not on AllDirectories.
The problem is in this line:
FileInfo[] fiArr = di.GetFiles(".", SearchOption.AllDirectories);
Change it to:
FileInfo[] fiArr = di.GetFiles(".", SearchOption.TopDirectoryOnly);
This should work.
Some SpecialFolders needs specific Admin priviledges to run without any exception. You must run your code in Admin priviledges.

C# Reading Paths From Text File Says Path Doesn't Exist [duplicate]

This question already has answers here:
What's the fastest way to read a text file line-by-line?
(9 answers)
Closed 7 years ago.
I'm developing a small command line utility to remove files from a directory. The user has the option to specify a path at the command line or have the paths being read from a text file.
Here is a sample text input:
C:\Users\MrRobot\Desktop\Delete
C:\Users\MrRobot\Desktop\Erase
C:\Users\MrRobot\Desktop\Test
My Code:
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Number of command line parameters = {0}", args.Length);
if(args[0] == "-tpath:"){
clearPath(args[1]);
}
else
if(args[0] == "-treadtxt:"){
readFromText(args[1]);
}
}
public static void clearPath(string path)
{
if(Directory.Exists(path)){
int directoryCount = Directory.GetDirectories(path).Length;
if(directoryCount > 0){
DirectoryInfo di = new DirectoryInfo(path);
foreach (DirectoryInfo dir in di.GetDirectories())
{
dir.Delete(true);
}
}
else{
Console.WriteLine("No Subdirectories to Remove");
}
int fileCount = Directory.GetFiles(path).Length;
if(fileCount > 0){
System.IO.DirectoryInfo di = new DirectoryInfo(path);
foreach (FileInfo file in di.GetFiles())
{
file.Delete();
}
}
else{
Console.WriteLine("No Files to Remove");
}
}
else{
Console.WriteLine("Path Doesn't Exist {0}", path);
}
}
public static void readFromText(string pathtotext)
{
try
{ // Open the text file using a stream reader.
using (StreamReader sr = new StreamReader(pathtotext))
{
// Read the stream to a string, and write the string to the console.
string line = sr.ReadToEnd();
clearPath(line);
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
}
}
My Problem:
When reading from the text file, it says that the first path doesn't exist, and prints all the paths to the prompt, despite that I have no Console.WriteLine(). However, if I plug these same paths and call -tPath: it will work. My issue seems to be in the readFromText() I just can't seem to figure it out.
This is the problem:
string line = sr.ReadToEnd();
That isn't reading a line of data - it's reading the whole file in one go. Your clearPath method expects its parameter to be a single path, not a bunch of lines glued together. The reason you're seeing all the paths is that clearPath is being called (with everything in one call), that "glued together" path isn't being found, and it's printing out the input in Console.WriteLine("Path Doesn't Exist {0}", path);.
I suspect you should use something like:
var lines = File.ReadAllLines(pathtotext);
foreach (var line in lines)
{
clearPath(pathtotext);
}

What is the best way to copy a list of files with these variable filenames using Path.Combine

I have source directories c:\source\yyyy-MM-dd where yyyy-MM-dd represents a range of dates, and a destination directory e:\destination. I need to look for multiple filenames in each date directory in that range of dates and only copy (filenameA*.*, filenameB*.*, filenameC*.*). I then need to create the date directories from the range of dates and copy the associated files found into their respective directories.
I'm using two datetimepickers to get the range of dates. I have that foreach logic working fine. I'm only struggling with the best way to use Path.Combine to create the destination folders and copy each of the files. I think I'm doing unnecessary work in my existing code, and I keep confusing myself:
private async void ProcessFiles()
{
// create a list of topics
var topics = topicsBox.CheckedItems.Cast<string>().ToList();
// create a list of source directories based on date range
var directories = new List<string>();
var folders = new List<string>();
for (DateTime date = dateTimePicker1.Value.Date;
date.Date <= dateTimePicker2.Value.Date;
date = date.AddDays(1))
{
var dateDir = _tracePath + #"\" + date.ToString("yyyy-MM-dd") + #"\";
directories.Add(dateDir);
folders.Add(#"\" + date.ToString("yyyy-MM-dd") + #"\");
}
// create a list of source files to copy and destination
foreach (var path in directories)
{
var path1 = path;
try
{
foreach (var files2 in folders)
{
var destPath = textBox1.Text + #"\" + textBox4.Text + files2;
foreach (var files in topics)
{
if (!Directory.Exists(path1))
{
toolStripStatusLabel1.ForeColor = Color.Red;
toolStripStatusLabel1.Text = ("Could not find \"" + path1 +
"\" Check start and end date.");
}
else
{
foreach (
string sourcePath in
Directory.EnumerateFiles(path1, files + "*.*", SearchOption.AllDirectories))
{
var filename = Path.GetFileName(sourcePath); // get each filename in source directory
var fullDestPath = Path.Combine(destPath, filename); // create the destination folder name
Directory.CreateDirectory(sourcePath.Replace(sourcePath, destPath)); // create the destination folder
// copy the files to the temp folder asynchronously
using (FileStream SourceStream = File.Open(sourcePath, FileMode.Open))
{
using (FileStream DestinationStream = File.Create(fullDestPath))
{
xferBtn.Enabled = false;
toolStripStatusLabel1.ForeColor = Color.Green;
toolStripStatusLabel1.Text = "Copying " + sourcePath;
await SourceStream.CopyToAsync(DestinationStream);
toolStripStatusLabel1.Text = "Copying complete!";
}
}
}
}
}
}
}
catch (Exception e)
{
}
}
}
To start, it may be easier to break things apart into separate methods to keep track of tasks. I find this to be easier when doing multiple tasks in one method. I just created a simple test to copy files from a source to destination. This won't match your logic, but it may lead you in the right direction. When you enumerate over files, you get an IEnumerable object to work with. You can use that to just iterate over your file paths. Also, you have a DirectoryInfo object you can use to check for directory creation before copying. I also did not follow your logic with source/destination stream, but instead just used the System.File.IO.Copy method that show how Path.Combine works. This is an easy way to combine say a path to a directory and a file without concatenation. Its basically a string.Format("{0}", somthingToAppend).
private void BtnProcess_Click(object sender, EventArgs e)
{
// create a list of source directories based on date range
List<string> sourceDirectories = new List<string>();
List<string> destDirectories = new List<string>();
sourceDirectories.Add("C:\\Users\\Eric\\Desktop\\Dir1");
sourceDirectories.Add("C:\\Users\\Eric\\Desktop\\Dir2");
destDirectories.Add("C:\\Users\\Eric\\Desktop\\Dest1");
destDirectories.Add("C:\\Users\\Eric\\Desktop\\Dest2");
// create a list of source files to copy and destination
foreach (var path in sourceDirectories)
{
if (!Directory.Exists(path))
{
//Error message here if path does not exist or continue with the next path
continue;
}
try
{
IEnumerable<string> paths = Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories);
DirectoryInfo destPathInfo = Directory.CreateDirectory(destDirectories[0]); // create the destination folder
if (destPathInfo.Exists)
{
foreach (var p in paths)
{
string destination = System.IO.Path.Combine(destDirectories[0], System.IO.Path.GetFileName(p));
System.IO.File.Copy(p, destination);
}
destDirectories.RemoveAt(0);
}
}
catch (Exception ex)
{
}
}
}

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

Categories