ASP.NET C# Copy Directory with SubDirectories with System.IO - c#

I need to copy a whole directory C:\X to C:\Y\X, and I need the sub-folders to be copied as well.
Is there any way to do it with the System.IO.File\Directory namespaces ?
Thanks for all helpers!

This class will copy or move a folder, without recursive calls.
The methods is using their own stacks to handle recursion, this is to avoid StackOverflowException.
public static class CopyFolder
{
public static void CopyDirectory(string source, string target)
{
var stack = new Stack<Folders>();
stack.Push(new Folders(source, target));
while (stack.Count > 0)
{
var folders = stack.Pop();
Directory.CreateDirectory(folders.Target);
foreach (var file in Directory.GetFiles(folders.Source, "*.*"))
{
string targetFile = Path.Combine(folders.Target, Path.GetFileName(file));
if (File.Exists(targetFile)) File.Delete(targetFile);
File.Copy(file, targetFile);
}
foreach (var folder in Directory.GetDirectories(folders.Source))
{
stack.Push(new Folders(folder, Path.Combine(folders.Target, Path.GetFileName(folder))));
}
}
}
public static void MoveDirectory(string source, string target)
{
var stack = new Stack<Folders>();
stack.Push(new Folders(source, target));
while (stack.Count > 0)
{
var folders = stack.Pop();
Directory.CreateDirectory(folders.Target);
foreach (var file in Directory.GetFiles(folders.Source, "*.*"))
{
string targetFile = Path.Combine(folders.Target, Path.GetFileName(file));
if (File.Exists(targetFile)) File.Delete(targetFile);
File.Move(file, targetFile);
}
foreach (var folder in Directory.GetDirectories(folders.Source))
{
stack.Push(new Folders(folder, Path.Combine(folders.Target, Path.GetFileName(folder))));
}
}
Directory.Delete(source, true);
}
public class Folders
{
public string Source { get; private set; }
public string Target { get; private set; }
public Folders(string source, string target)
{
Source = source;
Target = target;
}
}
}

This is copied from xneurons blog.
public static void CopyAll(DirectoryInfo source, DirectoryInfo target) {
// Check if the target directory exists, if not, create it.
if (Directory.Exists(target.FullName) == false) {
Directory.CreateDirectory(target.FullName);
}
// Copy each file into it’s new directory.
foreach (FileInfo fi in source.GetFiles()) {
Console.WriteLine(#"Copying {0}\{1}", target.FullName, fi.Name);
fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
}
// Copy each subdirectory using recursion.
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories()) {
DirectoryInfo nextTargetSubDir =
target.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir);
}
}

You can use SearchOption.AllDirectories to recursively search down folders, you just need to create the directories before you copy...
// string source, destination; - folder paths
int pathLen = source.Length;
foreach (string dirPath in Directory.GetDirectories(source, "*", SearchOption.AllDirectories))
{
string subPath = dirPath.SubString(pathLen);
string newpath = Path.Combine(destination, subPath);
Directory.CreateDirectory(newpath );
}
foreach (string filePath in Directory.GetFiles(source, "*.*", SearchOption.AllDirectories))
{
string subPath = filePath.SubString(pathLen);
string newpath = Path.Combine(destination, subPath);
File.Copy(filePath, newpath);
}

Related

How to prevent recursive in copying files and dirs?

I bumped into the problem with copying files/dirs. Been struggling almost for whole day.
I have to copy from root dir files and its dires with files and subdirs.
Actually, i've made something. However, every time i run in the stackoverflow error.
abstract class SystemOperations {
public virtual void SearchFiles() { }
public virtual void SearchDirectories() { }
public abstract void CreateDirectory(string DIR);
public abstract void CloneContent(string DIR);
public abstract void CreateJSON(string DIR);
public void ExecuteCopying(string DIR) {
CreateDirectory(DIR);
CloneContent(DIR);
CreateJSON(DIR);
}
}
class FileOperations : SystemOperations {
DirectoryInfo _MainPath;
public DirectoryInfo MainPath {
get { return _MainPath; }
set { _MainPath = value; }
}
public FileOperations(DirectoryInfo MainPath) {
this.MainPath = MainPath;
}
#region Unnecessary for current task
public override void SearchFiles() {
string path = "";
FileInfo[] files = MainPath.GetFiles();
foreach (FileInfo file in files) {
path = file.Name;
}
}
public override void SearchDirectories() {
string path = "";
DirectoryInfo[] directories = MainPath.GetDirectories();
foreach (DirectoryInfo directory in directories) {
path = directory.Name;
}
}
#endregion
public override void CreateDirectory(string DIR) {
string newFolder = Path.Combine(MainPath + "", DIR);
Directory.CreateDirectory(newFolder);
}
public override void CloneContent(string DIR) {
foreach (var directory in Directory.GetDirectories(MainPath + "")) {
string dir = Path.GetFileName(directory);
CloneContent(Path.Combine(MainPath + "", dir));
}
foreach (var file in Directory.GetFiles(MainPath + "")) {
File.Copy(file, Path.Combine(MainPath + "", Path.GetFileName(file)), true);
}
}
public override void CreateJSON(string DIR) {
if (!Directory.Exists(DIR)) {
var asd = new DirectoryInfo(DIR);
}
}
}
class Program {
static void Main() {
SystemOperations task = new FileOperations(new DirectoryInfo(#"D:\\LAK"));
task.ExecuteCopying("COPY");
}
}
So, the function CloneContent has to copy in each dir/subdirs files. But its recursive func and as i written above, i run to the error. And dont know how to fix this one. Thank u!
There is some kind of problem with the way you are trying to determine which directory you need to search next, the use of MainPath looks wrong to me.
Personally i also always prefer to have a secondary stop condition to avoid a StackOverflowException, like the maxrunCount i use below.
If you want a recursive directory lookup you should rewrite your code to something like
void Main()
{
string MainPath = "D:\\LAK";
// unless your directory is actually named \LAK:) you should use either #"D:\LAK" or "d:\\LAK"
CloneContent(MainPath,1000);
}
public void CloneContent(string directoryToSearch, int maxrunCount)
{
if(maxrunCount==0)
return;
System.Diagnostics.Debug.Print(directoryToSearch);
string[] directories = null;
try
{
directories = Directory.GetDirectories(directoryToSearch);
}
catch(UnauthorizedAccessException ex) {
System.Diagnostics.Debug.Print($"No access to dir {directoryToSearch}");
directories = new string[0];
}
// ensure you have access to the current directoryToSearch
foreach (var directory in directories)
{
CloneContent(directory,--maxrunCount);
}
System.Diagnostics.Debug.Print($"cloning {directoryToSearch}");
// .... do the actual cloning here,
// you will end up here when there are no more subdirectories on the current branch
}
For a recursive method to work, it must have at least one "exit" condition - the point at which it's done its job and can unwind the stack. In our case, it would be when there are no more direcories or files to copy from the source to the destination.
One way of writing this method would take in a source directory and a destination directory, and then it can recursively call itself for each sub-directory:
public static void CloneContent(string sourceDir, string destDir)
{
// If the source directory doesn't exist, return
if (!Directory.Exists(sourceDir)) return;
// Create destination if needed
Directory.CreateDirectory(destDir);
// Copy files from this directory to the new path
foreach (string file in Directory.GetFiles(sourceDir))
{
File.Copy(file, Path.Combine(destDir, Path.GetFileName(file)));
}
// Recursively call this method for each sub directory
foreach (string subDir in Directory.GetDirectories(sourceDir))
{
string dirName = Path.GetFileName(subDir);
string newSource = Path.Combine(sourceDir, dirName);
string newDest = Path.Combine(destDir, dirName);
CloneContent(newSource, newDest);
}
}

Object variable only showing the last value

The code below returns only the most recent value in the loop. What do I need to do for it to show all the values that are being iterated over? The reason I am using this method instead of SearchOption.AllDirectory is because there is a folder path I am not able to access. I did try using UnauthorizedAccessException with a try and catch, but that returns an empty value because it keeps on terminating the loop.
public void Main()
{
string path = #"drive"; // TODO
ApplyAllFiles(path, ProcessFile);
}
public void ProcessFile(string path)
{
/* ... */
}
public void ApplyAllFiles(string folder, Action<string> fileAction)
{
System.Collections.ArrayList FileList = new System.Collections.ArrayList();
List<string> logger = new List<string>();
DateTime DateFilter = DateTime.Now.AddMonths(-6);
foreach (string file in Directory.GetDirectories(folder))
{
fileAction(file);
}
foreach (string subDir in Directory.GetDirectories(folder))
{
string rootfolder = "root folder";
if (subDir.Contains(rootfolder))
{
FileList.Add(subDir);
Dts.Variables["User::objDirectoryList"].Value = FileList;
//MessageBox.Show(subDir);
}
try
{
ApplyAllFiles(subDir, fileAction);
}
catch (UnauthorizedAccessException e)
{
logger.Add(e.Message);
}
catch (System.IO.DirectoryNotFoundException e)
{
logger.Add(e.Message);
}
}
}
Try to remove the FileList declaration outside the function, also remove Dts.Variables["User::objDirectoryList"].Value = FileList; outside the loop:
System.Collections.ArrayList FileList = new System.Collections.ArrayList();
public void Main()
{
string path = #"drive"; // TODO
ApplyAllFiles(path, ProcessFile);
Dts.Variables["User::objDirectoryList"].Value = FileList;
}
public void ProcessFile(string path)
{
/* ... */
}
public void ApplyAllFiles(string folder, Action<string> fileAction)
{
List<string> logger = new List<string>();
DateTime DateFilter = DateTime.Now.AddMonths(-6);
foreach (string file in Directory.GetDirectories(folder))
{
fileAction(file);
}
foreach (string subDir in Directory.GetDirectories(folder))
{
string rootfolder = "root folder";
if (subDir.Contains(rootfolder))
{
FileList.Add(subDir);
//MessageBox.Show(subDir);
}
try
{
ApplyAllFiles(subDir, fileAction);
}
catch (UnauthorizedAccessException e)
{
logger.Add(e.Message);
}
catch (System.IO.DirectoryNotFoundException e)
{
logger.Add(e.Message);
}
}
}

How to load folder structure into treeview?

I want to Load Directory Structure Into TreeView. If there is a txt file in folder it must be break. Child folders and files should not shown. Please help me to find an algorithm
private void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));
}
private static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
{
if (directory.Name.EndsWith("txt"))
{
break;
}
else
{
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
}
}
foreach (var file in directoryInfo.GetFiles())
{
if (directoryNode.Name.EndsWith("txt"))
{
directoryNode.Nodes.Add(new TreeNode(file.Name));
}
}
return directoryNode;
}
I solved it like that,
private static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
try
{
int flag = 0;
foreach (var file in directoryInfo.GetFiles())
{
if (file.Name.EndsWith("txt"))
{
flag = 1;
}
}
if (flag == 0)
{
foreach (var directory in directoryInfo.GetDirectories())
{
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
}
}
return directoryNode;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}

Return type of all sub directories from a given path

hi i am doing my project i mvc4 using c#. I am trying to get all sub directories in a directory.and list it in my view
for that i am writing the following code
controller
public ActionResult Gallery()
{
string folderpath = Server.MapPath("~/Content/Gallery/GalleryImages");
List<string> currentimage = new Gallery().GetGalleryName(folderpath);
//What will be the return type???/
return View(currentimage);
}
model
public List<string> GetGalleryName(string path)
{
DirectoryInfo di = new DirectoryInfo(path);
DirectoryInfo[] subdir = di.GetDirectories();
List<String> files = new List<String>();
foreach (DirectoryInfo dir in subdir)
{
var name = dir.Name;
files.Add(name);
}
return files;
}
Is my code is right? then what will be the return type in controller and model? please help me
Change foreach loop in controller to
foreach (DirectoryInfo dir in subdir)
{
files.Add(dir.Name);
}
and change your controller from
public ActionResult Gallery()
{
string folderpath = Server.MapPath("~/Content/Gallery/GalleryImages");
string[] currentimage = new Gallery().GetGalleryName(folderpath);
//What will be the return type???/
return View(currentimage);
}
to
public ActionResult Gallery()
{
string folderpath = Server.MapPath("~/Content/Gallery/GalleryImages");
List<String> currentimage = new Gallery().GetGalleryName(folderpath);
//What will be the return type???/
return View(currentimage);
}
i hvn't tried it, but this should work. hope it helps
change the foreach loop to below
foreach (DirectoryInfo dir in subdir)
{
files.Add(dir.FullName);
}
Try this in your controller
public ActionResult Gallery()
{
List<String> galleryList = new List<String>();
string folderpath = Server.MapPath("~/Content/Gallery/GalleryImages");
string[] currentimage = new Gallery().GetGalleryName(folderpath);
foreach (var folder in currentimage) {
galleryList.Add(folder);
}
return View(galleryList);
}

UnauthorizedAccessException while getting files

I am creating an application which finds duplication in files. When I search files like:
try
{
string[] allFiles = Directory.GetFiles(
directoryPath, "*.*", SearchOption.AllDirectories
);
for (int i = 0; i < allFiles.Length; i++)
{
//decisions
}
}
catch (UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}
it says
Access to path 'C:\$Recycle.Bin....... ' is denied.
I want if a folder is not accessible then move to the next but execution of program stops at Directory.GetFiles method.
Here's a class that will work:
public static class FileDirectorySearcher
{
public static IEnumerable<string> Search(string searchPath, string searchPattern)
{
IEnumerable<string> files = GetFileSystemEntries(searchPath, searchPattern);
foreach (string file in files)
{
yield return file;
}
IEnumerable<string> directories = GetDirectories(searchPath);
foreach (string directory in directories)
{
files = Search(directory, searchPattern);
foreach (string file in files)
{
yield return file;
}
}
}
private static IEnumerable<string> GetDirectories(string directory)
{
IEnumerable<string> subDirectories = null;
try
{
subDirectories = Directory.EnumerateDirectories(directory, "*.*", SearchOption.TopDirectoryOnly);
}
catch (UnauthorizedAccessException)
{
}
if (subDirectories != null)
{
foreach (string subDirectory in subDirectories)
{
yield return subDirectory;
}
}
}
private static IEnumerable<string> GetFileSystemEntries(string directory, string searchPattern)
{
IEnumerable<string> files = null;
try
{
files = Directory.EnumerateFileSystemEntries(directory, searchPattern, SearchOption.TopDirectoryOnly);
}
catch (UnauthorizedAccessException)
{
}
if (files != null)
{
foreach (string file in files)
{
yield return file;
}
}
}
}
You can the use it like this:
IEnumerable<string> filesOrDirectories = FileDirectorySearcher.Search(#"C:\", "*.txt");
foreach (string fileOrDirectory in filesOrDirectories)
{
// Do something here.
}
It's recursive, but the use of yield gives it a low memory footprint (under 10KB in my testing). If you want only files that match the pattern and not directories as well just replace EnumerateFileSystemEntries with EnumerateFiles.

Categories