Copy all files in directory - c#

How can I copy all of the contents in one directory to another with out looping over each file?

You can't. Neither Directory nor DirectoryInfo provide a Copy method. You need to implement this yourself.
void Copy(string sourceDir, string targetDir)
{
Directory.CreateDirectory(targetDir);
foreach(var file in Directory.GetFiles(sourceDir))
File.Copy(file, Path.Combine(targetDir, Path.GetFileName(file)));
foreach(var directory in Directory.GetDirectories(sourceDir))
Copy(directory, Path.Combine(targetDir, Path.GetFileName(directory)));
}
Please read the comments to be aware of some problems with this simplistic approach.

Msdn has guidance on this - How to:Copy Directories

You can use VB’s FileSystem.CopyDirectory method to simplify the task:
using Microsoft.VisualBasic.FileIO;
foo(){
FileSystem.CopyDirectory(directoryPath, tempPath);
}

using System.IO;
string sourcePath = #"D:\test";
string targetPath = #"D:\test_new";
if (!Directory.Exists(targetPath))
{
Directory.CreateDirectory(targetPath);
}
foreach (var srcPath in Directory.GetFiles(sourcePath))
{
//Copy the file from sourcepath and place into mentioned target path,
//Overwrite the file if same file is exist in target path
File.Copy(srcPath, srcPath.Replace(sourcePath, targetPath), true);
}

KISS – Keep It Simple Stupid… is a good rule of thumb for any situation, including programming.
Here is the simplest method of copying all files, folders, sub-folders and all their files and folders while keeping the original hierarchy. It also displays a nice Microsoft Windows progress dialog box.
Simply follow these basic instructions:
1: Open a new C# console application in Visual Studio – version (whatever)
2: From the menu bar; go to “Tools – Nuget Package Manager – Manage Nuget Packages for Solution” In the Nuget package manager search box, type – “Microsoft.VisualBasic” and select the “.Net” package.
3: Back on the “Program.cs” page, add the following “using” statements:
• Using System;
• Using Microsoft.VisualBasic.FileIO;
4: Inside the “Main” method, type the code provided below, replacing the source and destination paths with your folder/drives.
5: The “Console.WriteLine” line simply displays a message that it is copying and to “Please Stand by”. This line of code is completely optional. Not needed for this process to work.
6: The “FileSystem.CopyDirectory” command is a basic copy function to copy the folder and contents to the new destination. The only real difference is that the “UIOption.AllDialgs” command is added to the end of the copy command. This is the part that generates the Microsoft Windows Progress Dialog box.
Now, add the following code to your C# “Program.cs” page.
using System;
using Microsoft.VisualBasic.FileIO;
namespace ProgressDialogBox
{
class Program
{
static void Main(string[] args)
{
string sourcePath = #"c:\TestA\TestNew3";
string destinationPath = #"c:\TestB\TestNew4";
Console.WriteLine(#"Copying... {0} ... Please stand by ", sourcePath);
FileSystem.CopyDirectory(sourcePath, destinationPath, UIOption.AllDialogs);
}
}
}
This whole process takes less than 3 minutes to create. It actually takes longer to read this posting than to create and execute the program.
Enjoy.
Hope this helps someone in the future.
Here is the link from Microsoft that I used for reference:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/file-system/how-to-provide-a-progress-dialog-box-for-file-operations

This works great! It will copy sub directories or you can just dump all the files from all subdirectories into one location.
/// AUTHOR : Norm Petroff
/// <summary>
/// Takes the files from the PathFrom and copies them to the PathTo.
/// </summary>
/// <param name="pathFrom"></param>
/// <param name="pathTo"></param>
/// <param name="filesOnly">Copies all files from each directory to the "PathTo" and removes directory.</param>
public static void CopyFiles(String pathFrom, String pathTo, Boolean filesOnly)
{
foreach(String file in Directory.GetFiles(pathFrom))
{
// Copy the current file to the new path.
File.Copy(file, Path.Combine(pathTo, Path.GetFileName(file)), true);
}
// Get all the directories in the current path.
foreach (String directory in Directory.GetDirectories(pathFrom))
{
// If files only is true then recursively get all the files. They will be all put in the original "PathTo" location
// without the directories they were in.
if (filesOnly)
{
// Get the files from the current directory in the loop.
CopyFiles(directory, pathTo, filesOnly);
}
else
{
// Create a new path for the current directory in the new location.
var newDirectory = Path.Combine(pathTo, new DirectoryInfo(directory).Name);
// Copy the directory over to the new path location if it does not already exist.
if (!Directory.Exists(newDirectory))
{
Directory.CreateDirectory(newDirectory);
}
// Call this routine again with the new path.
CopyFiles(directory, newDirectory, filesOnly);
}
}
}

Execute xcopy source_directory\*.* destination_directory as an external command. Of course this will only work on Windows machines.

You can't. But you can use some sort of succinct code like Directory.GetFiles(mydir).ToList().ForEach(f => File.Copy(f, otherdir + "\\" + Path.GetFileName(f));

While the C# approach works well, it's not always the best answer. A simple DOS batch script works much better by ignoring the 256 character limit found in the C# approach.
robocopy C:\myFiles D:\masterBackup\myFiles /E /V
The only draw back I have found with the DOS batch script is that it will not (in some cases) copy SQL Server "mdf" data files and "ldf" log files using the "robocopy" command. But that's a permissions issue.
Otherwise, I have relied more on the DOS batch script for my incremental and full backups.

Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + #"resources\html")
.ToList()
.ForEach(f => File.Copy(f, folder + "\\" + f.Substring(f.LastIndexOf("\\"))));

Related

c# FileInfo class being used in SSIS Script Task Directory.GetFiles SearchOption.TopDirectoryOnly being ignored

I am using the following Script Task to enumerate over a file directory, then pull a list of files and load them into a Recordset Destination. I don't want to drill down past the directory I specified #"E:\Data Warehouse\Imports\TIMECLOCK" in my search. There's a subsequent folder inside TIMECLOCK called PROCESSED, where it's supposed to move the files into later. So I'm only trying to grab the ones in the folder above, TIMECLOCK. So I used the SearchOption.TopDirectoryOnly in the Directory.GetFiles function, but it's drilling down past that to the PROCESSED folder, as evidenced by my Data Viewer (see Data View screenshot after the code). At first I was using a variable to pass in the search directory, but it was doing the same thing, so I explicitly declared the search directory, and it's still not working. I don't know what I'm doing wrong!
#region Namespaces
using System;
using System.Data;
using System.IO;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
#endregion
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent{
public override void CreateNewOutputRows()
{
string sourceDirectory = #"E:\Data Warehouse\Imports\TIMECLOCK";
string searchFileName = "Business Units GL Segments_Sent Weekly*";
string[] files = Directory.GetFiles(sourceDirectory, searchFileName, SearchOption.TopDirectoryOnly);
FileInfo fileInfo = new FileInfo(sourceDirectory);
foreach (string file in files)
{
String FileFullPath = Path.GetFullPath(file);
fileInfo = new FileInfo(FileFullPath);
OrderedFilesBuffer.AddRow();
OrderedFilesBuffer.FileName = fileInfo.Name;
OrderedFilesBuffer.FileDate = fileInfo.LastWriteTime;
OrderedFilesBuffer.FilePath = fileInfo.FullName;
}
}
}
I am marking as answered because I am still completely not sure why this was happening, and I ultimately decided what I was trying to reproduce with writing the values to (2) file objects, then merging and getting a unique list of files between them to process, was really just a simple File Move task. I was writing this for a client who originally designed it in Pentaho Data Integration that way and was reproducing it exactly in SSIS, when it was not really necessary. I think since I was running both of these extractions simultaneously in the same Control Flow, it was using the same file path for both because of a cache issue of some sort and ignoring the TopDirectoryOnly. At any rate, I trashed it and re-did the whole thing.

Move Directory Into Current Directory C#

I want to do something simple. Take the contents of folder A and move the files and folders into a folder within folder A. Then make folder A hidden.
The code below is getting an exception of hiddenTarget is not found.
Directory.Create(hiddenTarget) is not helping
There must be a simple way to do this. Currently I am attempting to make a temp directory. Put all files from the current directory in it. Then Move the temp directory to the current directory. Then make the current directory hidden.
Here is the code in issue..
string tempFolder = Path.Combine(Environment.ExpandEnvironmentVariables("%TEMP%"), "tempTarget");
//Directory.CreateDirectory(tempFolder);
Directory.Move(currentTarget, tempFolder);
string hiddenTarget = Path.Combine(currentTarget, #".bak");
//Directory.CreateDirectory(hiddenTarget);
Directory.Move(tempFolder, hiddenTarget);
DirectoryInfo di = new DirectoryInfo(currentTarget);
di.Attributes = FileAttributes.Directory | FileAttributes.Hidden;
So you have two issues here first is that your hidden target cannot start with a '.' because as pointed out in the comments that is illegal in NTFS.
As you can see File Explorer doesn't like this syntax.
As pointed out by #Dour High Arch here is the link to the relevant information: Naming Files, Paths, and Namespaces
Your next issue is that the move is destroying the original directory structure. Therefore, your steps need to be as follows:
1) Move to a temporary directory to avoid any issues with the two processes (file system & your process) fighting for access.
2) Due to the fact that the Directory.Move in step #1 destroyed the original source directory. Recreate the destroyed source folder.
3) Then move into the desired nested folder. This move operation will automatically create the desired sub-directory. Step #2 is required because for whatever reason I'm still looking into Directory.Move cannot automatically create the structure without the source directory already existing.
string currentTarget = #"C:\A";
string hiddenTarget = #"C:\A\Subfolder";
string tempTarget = #"C:\Temp";
Directory.Move(currentTarget, tempTarget);
Directory.CreateDirectory(currentTarget);
Directory.Move(tempTarget, hiddenTarget);
DirectoryInfo di = new DirectoryInfo(currentTarget);
di.Attributes = FileAttributes.Directory | FileAttributes.Hidden;
Update
From an engineering perspective you really should be performing copies if you really care about the data being moved. It may be slower, but will help prevent any horrible things from happening to the data. You should check whether or not these directories exist first before creating them. Exception handling within this example is at a minimum as well. What I'm really trying to stress here is handle the data that is being moved with care!
static void Main(string[] args)
{
string sourceDir = #"C:\Src";
string tempDir = #"C:\Temp";
string destDir = Path.Combine(sourceDir, "Dest");
// Could optionally check to verify that the temp directory already exists here and destroy it if it does.
// Alternatively, pick a really unique name for the temp directory by using a GUID, Thread Id or something of that nature.
// That way you can be sure it does not already exist.
// Copy to temp, then destroy source files.
CopyDirectory(sourceDir, tempDir);
Directory.Delete(sourceDir, true);
// Copy to dest
CopyDirectory(tempDir, destDir);
// Hide the source directory.
DirectoryInfo di = new DirectoryInfo(sourceDir);
di.Attributes = FileAttributes.Directory | FileAttributes.Hidden;
// Clean up the temp directory that way copies of the files aren't sitting around.
// NOTE: Be sure to do this last as if something goes wrong with the move the temp directory will still exist.
Directory.Delete(tempDir, true);
}
/// <summary>
/// Recursively copies all subdirectories.
/// </summary>
/// <param name="sourceDir">The source directory from which to copy.</param>
/// <param name="destDir">The destination directory to copy content to.</param>
static void CopyDirectory(string sourceDir, string destDir)
{
var sourceDirInfo = new DirectoryInfo(sourceDir);
if (!sourceDirInfo.Exists)
{
throw new DirectoryNotFoundException($"Source directory does not exist or could not be found: '{sourceDir}'");
}
// If the destination directory doesn't exist, create it.
if (!Directory.Exists(destDir))
{
Directory.CreateDirectory(destDir);
}
// Get the files in the directory and copy them to the new location.
FileInfo[] files = sourceDirInfo.GetFiles();
foreach (FileInfo file in files)
{
string tempPath = Path.Combine(destDir, file.Name);
file.CopyTo(tempPath, false);
}
// Copy subdirectories
DirectoryInfo[] subDirs = sourceDirInfo.GetDirectories();
foreach (DirectoryInfo subdir in subDirs)
{
string tempPath = Path.Combine(destDir, subdir.Name);
CopyDirectory(subdir.FullName, tempPath);
}
}
Here are a few more links regarding the above.
MSDN - How to: Copy Directories
Stack Overflow - How to copy the entire contents of directory in C#?

How to get the folder path using folder name c#

I'm using C# to get the exact path of the specific folder in windows system by giving the folder name. Is their any way to get the folder path by giving the folder name, where the folder name will be unique.
Update:
Folder is created at run time with current time as the name. This
process is done by the application. Here i know the folder name but i
didn't know path, because path is selected by the user during
installation and installation is done before very long time.
That changes the question considerably. Why not use the application to tell you where it lives:
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.startuppath.aspx
I had a similar idea ages ago and wrote about it as a Code Project Tip:
http://www.codeproject.com/Tips/132804/Open-folders-using-a-Run-Command
Otherwise you would need to index every folder on the PC and make them unique names and look up the full path that way.
The other suggestion I have is using LogParser as the Most efficient way to find all exe files on disk using C#? Its a free Microsoft product but I'm not sure about re-dist permissions, I had to include it in my package separately last time I used it. It full on flys, faster than a speeding train!
I found a Log Parser example that finds folders, you could try it out and adapt it if its useful:
SELECT TOP 1 * FROM C:\TFS\Project\*.* WHERE INDEX_OF(Path, 'Database') > 0
The good folks over at http://visuallogparser.codeplex.com/ have
provided us with the source code.
Open the VisualLogParser solution in VS2010, ignore the prompt about debugging, after the solution loads, F5, set the combo-box to FS (FileSystem), paste in this query and press go.
You could probably use something like this, but it'll be rather slow, depending on how many folders needed to be looked through.
Use it like FindFullPath(rootFolder, folderNameToLookFor)
public static string FindFullPath(string path, string folderName)
{
if (string.IsNullOrWhiteSpace(folderName) || !Directory.Exists(path))
{
return null;
}
var di = new DirectoryInfo(path);
return findFullPath(di, folderName);
}
private static string findFullPath(DirectoryInfo directoryInfo, string folderName)
{
if (folderName.Equals(directoryInfo.Name, StringComparison.InvariantCultureIgnoreCase))
{
return directoryInfo.FullName;
}
try
{
var subDirs = directoryInfo.GetDirectories();
return subDirs.Select(subDir => findFullPath(subDir, folderName)).FirstOrDefault(fullPath => fullPath != null);
}
catch
{
// DirectoryNotFound, Security, UnauthorizedAccess
return null;
}
}
See following link
string dirName = new DirectoryInfo(#"c:\projects\roott\wsdlproj\devlop\beta2\text").Name;

Read a file from an unknown location?

I have got this read file code from microsoft
#"C:\Users\computing\Documents\mikec\assignment2\task_2.txt"
That works fine when im working on it, but when i am to hand in this assignment my lecturer isn't going to have the same directory as me.
So i was wondering if there is a way to read it from just the file the program is held in?.
I was thinking i could add it as a resource but im not sure if that is the correct way for the assignment it is meant to allow in any file.
Thanks
You can skip the path - this will read file from the working directory of the program.
Just #"task_2.txt" will do.
UPDATE: Please note that method won't work in some circumstances. If your lecturer uses some automated runner (script, application whatsoever) to verify your app then #ken2k's solution will be much more robust.
If you want to read a file from the directory the program is in, then use
using System.IO;
...
string myFileName = "file.txt";
string myFilePath = Path.Combine(Application.StartupPath, myFileName);
EDIT:
More generic solution for non-winforms applications:
string myFilePath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), myFileName);
If it is a command line application, you should take the file name as a command line argument instead of using a fixed path. Something along the lines of;
public static void Main(string[] args)
{
if (args == null || args.Length != 1)
{
Console.WriteLine("Parameters are not ok, usage: ...");
return;
}
string filename = args[0];
...
...should let you get the filename from the command.
You could use the GetFolderPath method to get the documents folder of the current user:
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
and to exemplify:
string myDocuments = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string file = Path.Combine(myDocuments, #"mikec\assignment2\task_2.txt");
// TODO: do something with the file like reading it for example
string contents = File.ReadAllText(file);
Use the relative path.
you can put your file inside the folder where your application resides.
you can use Directory.GetCurrentDirectory().ToString() method to get the current folder of the application in. if you put your files inside a sub folder you can use
Directory.GetCurrentDirectory().ToString() + "\subfolderName\"
File.OpenRead(Directory.GetCurrentDirectory().ToString() + "\fileName.extension")
StreamReader file = new StreamReader(File.OpenRead(Directory.GetCurrentDirectory().ToString() + ""));
string fileTexts = file.ReadToEnd();

UnauthorizedAccessException trying to delete a file in a folder where I can delete others files with the same code

I'm getting a Unauthorized Access Exception
in a file which I can delete manually.
in a folder where I'm able to delete by code other files
and the file isn't marked as read only
besides, I'm using Windows XP in a standalone PC and I have not assigned any permissions to the folder or the file.
no other process is using the file
If it helps, this is the code where the exception ocurrs:
protected void DeleteImage(string imageName)
{
if (imageName != null)
{
string f = String.Format("~/Images/{0}", imageName);
f = System.Web.Hosting.HostingEnvironment.MapPath(f);
if (File.Exists(f))
{
if (f != null) File.Delete(f);
}
}
}
Why could this happen?
I encountered the same problem, and found that writing my own Directory.Delete wrapper fixed it up. This is recursive by default:
using System.IO;
public void DeleteDirectory(string targetDir)
{
File.SetAttributes(targetDir, FileAttributes.Normal);
string[] files = Directory.GetFiles(targetDir);
string[] dirs = Directory.GetDirectories(targetDir);
foreach (string file in files)
{
File.SetAttributes(file, FileAttributes.Normal);
File.Delete(file);
}
foreach (string dir in dirs)
{
DeleteDirectory(dir);
}
Directory.Delete(targetDir, false);
}
If the directory contains a read only file, it won't delete that using Directory.Delete. It's a silly implementation by MS.
I am surprised no one suggested this method on the internet, which deletes the directory without recursing through it and changing every file's attributes. Here's that:
Process.Start("cmd.exe", "/c " + #"rmdir /s/q C:\Test\TestDirectoryContainingReadOnlyFiles");
(Change a bit to not to fire a cmd window momentarily, which is available all over the internet)
If it's not read-only it's possible that it is currently in use by another process.
Checking the obvious first...
When you open the file property and take a look at its security settings. Does the user running the code (i.e. if this is ASP.NET, Network Services / Domain Service Account) has access to actually delete the file?
If it is not, then change it and try again.
Are you running as administrator when trying to delete this manually?
If you are, then that's probably why you are able to delete it manually. Try deleting it as the account running your ASP.NET (I'm assuming it is ASP.NET since you are using System.Web.Hosting.HostingEnvironment.MapPath.)
If both failed, try to see if any other process is actually currently using this file. Good tool to find out is SysInternal Process Monitor. Filter it by path containing your filename and you should see if anything is using it. Terminate the process and try again.
I too faced the Same Problem but eventually came up with a Generic Approach. Below are my codes.
String pathfile = "C:\Users\Public\Documents\Filepath.txt" ;
if (!Directory.Exists(pathfile))
{
File.SetAttributes(pathfile, FileAttributes.Normal);
File.Delete(pathfile);
}
using (FileStream fs = File.Create(pathfile))
{
Byte[] info = new UTF8Encoding(true).GetBytes("What Ever Your Text is");
fs.Write(info, 0, info.Length);
File.SetAttributes(pathfile, FileAttributes.ReadOnly);
}
You, the human user, have a login with certain rights. The Web server might have a different login with different rights. A user starting with IUSR_XXXX or some such thing. Make sure that user has rights to the directory.
Without more info on the context in which you are deleting the file, I assume that the Web server user has different rights to a file than you do.

Categories

Resources