I am trying to take a directory and create a new directory in TEMP, that contains all the files in the original directory, but not create additional sub-directories.
Here is what I have so far:
Directory.CreateDirectory(Path.Combine(Path.GetTempPath() + "C# Temporary Files"));
string lastFolder = new DirectoryInfo(folders.SelectedPath).Name;
foreach (string newPath in Directory.GetFiles(folders.SelectedPath, "*.*",SearchOption.AllDirectories)
.Where(s=>s.EndsWith(".c")|| s.EndsWith(".h")))
{
File.Copy(newPath, newPath.Replace(folders.SelectedPath, Path.GetTempPath() + "C# Temporary Files\\" + GlobalVar.GlobalInt));
}
This works in copying files that are in the directory itself, but not files in subdirectories. Instead it throws the error:
System.IO.DirectoryNotFoundException.
An example of the error:
Could not find a part of the path
'C:\Users\username\AppData\Local\Temp\C# Temporary Files\outer
directory\sub-directory\filename'.
I'd it recursively - maybe something like the below pseudo code... not tested..
public void CopyRecursive(string path, string newLocation)
{
foreach(var file in DirectoryInfo.GetFiles(path))
{
File.Copy(file.FullName, newLocation + file.Name);
}
foreach(var dir in DirectoryInfo.GetDirectories(path))
{
CopyRecursive(path + dir.Name, newLocation);
}
}
Related
I have some folders and these folders have some text files and i need delete these files but i catch an error with my code!
var dateFolder = Directory.GetDirectories(#"data\stdate").Select(Path.GetDirectoryName).ToArray();
foreach (var dateFile in dateFolder)
{
var stDates =
Directory.GetFiles(#"data\stdate\" + dateFile + "date").Select(Path.GetFileName).ToArray();
foreach (var date in stDates)
{
File.Delete(#"data\stdate\" + dateFile + "date\\" + date);
}
Directory.Delete(#"data\stdate\" + dateFile + "date");
}
try this:
Directory.Delete("Path", true); //true: It will delete directory by given path, also folders and files in it.
System.IO.DirectoryInfo di = new DirectoryInfo(#"data\stdate");
//This for delete all file in "data\stdate"
foreach (FileInfo file in di.GetFiles())
{
file.Delete();
}
//***************************For delete file in folder
//This for delete all Subfolder and his files in "data\stdate"
foreach (DirectoryInfo dir in di.GetDirectories())
{
dir.Delete(true);
}
//*************************
//This for delete the parent folder "stdate"
di.Delete();
i delete my original folder and i create it again!
if (!isDateEmpty)
{
Directory.Delete(#"data\stdate", true);
Directory.CreateDirectory(#"data\stdate");
}
I suggest that you use system environment variables, see here:
https://en.wikipedia.org/wiki/Environment_variable
The reason being, like you found out: sometimes the executable is not running in the directory you expected when you compiled the program.
EX:
String query = "%SystemDrive%";
str = Environment.ExpandEnvironmentVariables(query);
Delete(str, true);
That way it guarantees a predictable path as opposed to a relative one.
I have the following script, which take a source folder and copy using FileStream files to another folder.
I need to change it in a way to recursively get any sub-folders and copy their files too.
How to modifythe method?
- source folder
- file
- file
- folder
- file
- file
- folder
- file
- folder
- file
- file
- folder
- file
public static void SynchFolders()
{
DirectoryInfo StartDirectory = new DirectoryInfo(SourceUNC);
DirectoryInfo EndDirectory = new DirectoryInfo(TargetUNC);
foreach (FileInfo file in StartDirectory.EnumerateFiles())
{
using (FileStream SourceStream = file.OpenRead())
{
string dirPath = StartDirectory.FullName;
string outputPath = dirPath.Replace(StartDirectory.FullName, EndDirectory.FullName);
using (FileStream DestinationStream = File.Create(outputPath + "\\" + file.Name))
{
SourceStream.CopyToAsync(DestinationStream);
}
}
}
}
Basically what you need to do is to expand your function slightly such that after copying all files found in a particular directory, it will then search for subfolders within the current folder and recurse into that folder so that the same procedure is carried out on each subfolder.
An example function, based on your original code :
public static void SynchFolders(string SourceUNC, string TargetUNC)
{
DirectoryInfo StartDirectory = new DirectoryInfo(SourceUNC);
DirectoryInfo EndDirectory = new DirectoryInfo(TargetUNC);
// Copy Files
foreach (FileInfo file in StartDirectory.EnumerateFiles())
{
using (FileStream SourceStream = file.OpenRead())
{
string dirPath = StartDirectory.FullName;
string outputPath = dirPath.Replace(StartDirectory.FullName, EndDirectory.FullName);
using (FileStream DestinationStream = File.Create(outputPath + "\\" + file.Name))
{
SourceStream.CopyToAsync(DestinationStream);
}
}
}
// Copy subfolders
var folders = StartDirectory.EnumerateDirectories();
foreach (var folder in folders)
{
// Create subfolder target path by concatenating folder name to original target UNC
string target = Path.Combine(TargetUNC, folder.Name);
Directory.CreateDirectory(target);
// Recurse into the subfolder
SynchFolders(folder.FullName, target);
}
}
Hope this helps
How to: Copy Directories is an article from MSDN showing how to do exactly what you need.
Read this MSDN Tutorial (exacly what you need): http://msdn.microsoft.com/en-us/library/bb762914(v=vs.110).aspx
Note: if you'd like to use SourceStream.CopyToAsync instead of file.CopyTo, just replace it with your original snippet
I'm trying this function, which copies all files from a folder, and relative subfolders with files to another location:
using System.IO;
private static bool CopyDirectory(string SourcePath, string DestinationPath, bool overwriteexisting)
{
bool ret = true;
try
{
SourcePath = SourcePath.EndsWith(#"\") ? SourcePath : SourcePath + #"\";
DestinationPath = DestinationPath.EndsWith(#"\") ? DestinationPath : DestinationPath + #"\";
if (Directory.Exists(SourcePath))
{
if (Directory.Exists(DestinationPath) == false)
Directory.CreateDirectory(DestinationPath);
foreach (string fls in Directory.GetFiles(SourcePath))
{
FileInfo flinfo = new FileInfo(fls);
flinfo.CopyTo(DestinationPath + flinfo.Name, overwriteexisting);
}
foreach (string drs in Directory.GetDirectories(SourcePath))
{
DirectoryInfo drinfo = new DirectoryInfo(drs);
if (CopyDirectory(drs, DestinationPath + drinfo.Name, overwriteexisting) == false || drs.Substring(drs.Length-8) == "archive")
ret = false;
}
}
else
{
ret = false;
}
}
catch (Exception e)
{
Console.WriteLine("{0} {1} {2}", e.Message, Environment.NewLine + Environment.NewLine, e.StackTrace);
ret = false;
}
return ret;
}
It works good until you have to copy the folder into another location, but when you have to create a folder in itself (In my example I'm doing a subfolder called "archive" to keep track of the last folder files changes) it goes in infinite loops, because it keeps rescanning itself in the Directory.GetDirectories foreach loop, finding the newly created subfolders and going on nesting the same subfolder over and over until it reaches a "Path name too long max 260 charachters limit exception".
I tried to avoid it by using the condition
|| drs.Substring(drs.Length-8) == "archive")
which should check the directory name, but it doesn't seem to work.
I thought than, different solutions like putting a max subfolders depth scan (I.E max 2 subfolders) so it doesn't keep rescanning all the nested folders, but I can't find such property in Directory object.
I cannot copy the whole thing to a temp folder and then into the real folder because the next time I will scan it, it will rescan archive folder too.
I tought about putting all the directory listing in an ArrayList of Directory objects or so so maybe I can check something like DirName or so but I don't know if such property exists.
Any solution?
This is a case where recursion doesn't really work, as the list of directories and files always changes as you copy. A better solution is to get the list of all files and folders in advance.
You can get all files and directories in a tree using the Directory.GetFiles(String,String,SearchOption) and Directory.GetDirectories(String,String,SearchOption) with SearchOption set to SearchOption.AllDirectories. These will return all files and all directories respectively.
You can follow these steps to copy the files:
Get the list of all source directories and sort them in ascending order. This will ensure that parent directories appear before their child directories.
Create the target directory structure by creating the child directories in their sorted order. You won't get any path conflicts as the sort order ensures you always create the parent folders before the child folders
Copy all the source files to the target directories as before. Order doesn't really matter at this point as the target directory structure already exists.
A quick example:
static void Main(string[] args)
{
var sourcePath = #"c:\MyRoot\TestFolder\";
var targetPath = #"c:\MyRoot\TestFolder\Archive\";
var directories=Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories);
var files = Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories);
if(!Directory.Exists(targetPath))
Directory.CreateDirectory(targetPath);
foreach (var directory in directories)
{
var relativePath = GetRelativePath(sourcePath, directory);
var toPath = Path.Combine(targetPath, relativePath);
if (!Directory.Exists(toPath))
{
Directory.CreateDirectory(toPath);
}
}
foreach (var file in files)
{
var relativePath = GetRelativePath(sourcePath, file);
var toPath = Path.Combine(targetPath, relativePath);
if (!File.Exists(toPath))
File.Copy(file,toPath);
}
}
//This is a very quick and dirty way to get the relative path, only for demo purposes etc
private static string GetRelativePath(string rootPath, string fullPath)
{
return Path.GetFullPath(fullPath).Substring(rootPath.Length);
}
I wanna do a C# application that does this:
Selects a folder
Copies all the files from that folder into that folder +/results/
Very simple, but can't get it work.
Here is my code:
string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath);
foreach (string file in files)
{
MessageBox.Show(Path.GetFullPath(file));
//string path=Path.Combine(Path.GetFullPath(file), "results");
//MessageBox.Show(path);
string path2 = Path.GetDirectoryName(file);
path2 = Path.Combine(Path.GetDirectoryName(file), #"results\");
path2 = Path.Combine(path2, file);
MessageBox.Show(path2);
}
First, create the destination directory, if not exists
string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath);
string destPath = Path.Combine(folderBrowserDialog1.SelectedPath, "results");
if(Directory.Exists(destPath) == false)
Directory.CreateDirectory(destPath);
then inside your loop
foreach (string file in files)
{
string path2 = Path.Combine(destPath, Path.GetFileName(file));
File.Move(file, path2);
}
Please note that File.Move cannot be used to overwrite an existing file.
You will get an IOException if the file exist in the destination directory.
If you only want to copy, instead of Move, simply change the File.Move statement with File.Copy(file, path2, true);. This overload will overwrite your files in the destination directory without questions.
If you are trying to move the files (and not copy them) to the new sub-folder then...
DirectoryInfo d = new DirectoryInfo(folderBrowserDialog1.SelectedPath);
foreach (FileInfo f in d.GetFiles())
{
string fold = Path.Combine(f.DirectoryName, #"results\");
if (!Directory.Exists(fold))
Directory.CreateDirectory(fold);
File.Move(f.FullName, Path.Combine(fold, f.Name));
}
This is just an example to answer the question directly but you should also handle exceptions, etc. For instance, this example assumes the user will have permission to create the directory. Furthermore, it assumes file(s) do not already exist in the destination directory with the same name(s). How you handle such scenarios depends on your requirements.
If you want to relocate the entire directory, you can use Directory.Move to achieve this.
string path1 = Path.GetDirectoryName(file);
string path2 = Path.Combine(Path.GetDirectoryName(file), #"results\");
Directory.Move(path1, path2);
Or if you just want to copy the folder (without deleting the first directory), you'll need to do it manually.
string path1 = Path.GetDirectoryName(file);
string path2 = Path.Combine(Path.GetDirectoryName(file), #"results\");
foreach(var file in Directory.GetFiles(path1))
{
File.Copy(file, Path.Combine(path2, file));
// File.Move(file, Path.Combine(path2, file)); // use this to move instead of copy
}
I haven't tested this, so some modifications might be necessary
Background: I'm developing a WinForms application using C# with an OpenFileDialog & FileBrowserDialog that will 1) search for a specific string in the filenames of a specified source directory 2) copy files to consolidated directory 3) convert multiple files from excel to csv files, and then 3) convert all the generated csv files into 1 big csv file using a command line executable
Example: MSDN provides a code example that lists all of the directories and files that begin with the letter "c" in "c:\". at http://msdn.microsoft.com/en-us/library/ms143448.aspx so I based my code on that...
Problem: The code doesn't copy any files to the consolidated folder so I'm pretty sure the search doesn't work.
What should I change on here? It doesn't work :
string files = "*.xlsx";
void DirSearch(string sDir)
{
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d, files))
{
// Is this the file we are looking for?
// check excel files for corp name in the filename.
if (f.Contains(m_sc.get_Corp()))
{
// check if thread is cancelled
if (m_EventStop.WaitOne(0, true))
{
// clean-up operations may be placed here
// ...
// inform main thread that this thread stopped
m_EventStopped.Set();
return;
}
else
{
string path = sDir;
string searchPattern = m_sc.get_Corp();
// A file has been found in this directory
DirectoryInfo di = new DirectoryInfo(path);
DirectoryInfo[] directories = di.GetDirectories(searchPattern, SearchOption.TopDirectoryOnly);
foreach (FileInfo file in files)
{
try
{
// Copy each selected xlsx files into the specified TargetFolder
System.IO.File.Copy(FileName, consolidatedFolder + #"\" + System.IO.Path.GetFileName(FileName));
Log("File" + FileName + " has been copied to " + consolidatedFolder + #"\" + System.IO.Path.GetFileName(sourceFileOpenFileDialog.FileName));
// Convert each selected XLSX File to CSV Using the command prompt code...
}
}
}
}
The code you've posted does two separate search loops:
first:
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d, files))
{
// Is this the file we are looking for?
// check excel files for corp name in the filename.
if (f.Contains(m_sc.get_Corp()))
{
then within that it also does:
string path = sDir;
string searchPattern = m_sc.get_Corp();
// A file has been found in this directory
DirectoryInfo di = new DirectoryInfo(path);
DirectoryInfo[] directories = di.GetDirectories(searchPattern, SearchOption.TopDirectoryOnly);
foreach (FileInfo file in files)
{
In the first one you are looking for files matching m_sc.get_Corp();, in the second one you are lookinf for directories...
In fact... your code (pseudo-code?) makes no sense...
Try:
taking your time
tidying up the code yourself
if you rewrite it slowly and break this into smaller chunks, you might spot what you are doing wrong.
Try cleaning up a bit, below is some code that will put you on the path, I've excluded the CSV conversion and the merge, hopefully you will get the idea.
private void YourFileRoutine(string sourceDirectoryPath, string consolidatedDirectoryPath)
{
var excelFiles = new DirectoryInfo(sourceDirectoryPath).GetFiles().Where(x => x.Extension == ".xlsx");
//Copy all Excel Files to consolidated Directory
foreach (var excelFile in excelFiles)
{
FileInfo copiedFile = excelFile.CopyTo(String.Concat(consolidatedDirectoryPath, excelFile.Name)); // Make sure consolidatedDirectoryPath as a "\" maybe use Path.Combine()?
// ConvertToCSV( Do your CSV conversion here, the Path will be = Path.GetFullPath(copiedFile);
}
// Merge CSV's
var csvFiles = new DirectoryInfo(consolidatedDirectoryPath).GetFiles().Where(x => x.Extension == ".csv");
// SomeMergeMethod that iterates through this FileInfo collection?
}