I want to move a directory from one location to another using C# .NET. I used Directory.Move or even DirectoryInfo (with MoveTo) this simple way:
// source is: "C:\Songs\Elvis my Man"
// newLocation is: "C:\Songs\Elvis"
try
{
// Previous command was: Directory.Move(source, newLocation);
DirectoryInfo dir = new DirectoryInfo(source);
dir.MoveTo(newLocation);
}
catch (Exception e)
{
Console.WriteLine("Error: "+ e.Message);
}
But action that's being done (for both cases) is renaming the folder name from 'source' to 'newLocation'
What I expected? that folder "Elvis my man" will be now in "Elvis" folder.
What has happened? "Elvis my man" was changed to "Elvis" (Renamed). If the directory "Elvis" is already exists, it can't change it to "Elvis" (cause he can't make a duplicate names), therefore I get an exception saying that.
What am I doing wrong??
Many thanks!!!
I would advise putting validation around the Move command to ensure that the source location does exists and the destination location doesn't exists.
I've always found it easier to avoid the exceptions than handle them once they do occur.
You'll probably want to include exception handling as well, just in case the access permissions are a problem or a file is open and can't be moved...
Here's some sample code for you:
string sourceDir = #"c:\test";
string destinationDir = #"c:\test1";
try
{
// Ensure the source directory exists
if (Directory.Exists(sourceDir) == true )
{
// Ensure the destination directory doesn't already exist
if (Directory.Exists(destinationDir) == false)
{
// Perform the move
Directory.Move(sourceDir, destinationDir);
}
else
{
// Could provide the user the option to delete the existing directory
// before moving the source directory
}
}
else
{
// Do something about the source directory not existing
}
}
catch (Exception)
{
// TODO: Handle the exception that has been thrown
}
Even though this works in the command line to move a file, when programming you need to provide the full new name.
So you'd need to change newLocation to "C:\Songs\Elvis\Elvis my Man" to make this work.
From MSDN,
This method throws an IOException if, for example, you try to move c:\mydir to c:\public, and c:\public already exists. You must specify "c:\public\mydir" as the destDirName parameter, or specify a new directory name such as "c:\newdir".
It looks like you need to set newLocation to C:\Songs\Elvis\Elvis my man
private void moveDirectory(string fuente,string destino)
{
if (!System.IO.Directory.Exists(destino))
{
System.IO.Directory.CreateDirectory(destino);
}
String[] files = Directory.GetFiles(fuente);
String[] directories = Directory.GetDirectories(fuente);
foreach (string s in files)
{
System.IO.File.Copy(s, Path.Combine(destino,Path.GetFileName(s)), true);
}
foreach(string d in directories)
{
moveDirectory(Path.Combine(fuente, Path.GetFileName(d)), Path.Combine(destino, Path.GetFileName(d)));
}
}
Related
I need to check if the current user has write permissions inside the path. Here an example:
string save_path = #"C:\Windows\somefolder";
string my_dir = Path.DirectorySeparatorChar + "foobar";
//check if specific path are valid
if (!Directory.Exists(save_path)) { return; }
if (Directory.Exists(save_path + my_dir)) { return; }
if (canWriteOnPath(save_path)) {
Directory.CreateDirectory(save_path + my_dir);
} else {
//You are not allowed to save here OR not are launching this application as "administrator"
Directory.CreateDirectory(#"C:\Users\contoso\Documents\foobar");
}
solved in this question:
CurrentUserSecurity cus = new CurrentUserSecurity();
bool flag = cus.HasAccess(new DirectoryInfo(#"C:\Windows"), FileSystemRights.Write);
if (flag) {
//yes create that folder
Directory.CreateDirectory(Path.Combine(save_path, my_dir));
} else {
//NO YOU CANT
Directory.CreateDirectory(#"C:\Users\contoso\Documents\foobar");
}
The robust method would be to Try to create the directory and Catch any resulting exception.
The documentation for Directory.CreateDirectory lists the possible exceptions: IOException, UnauthorizedAccessException, ArgumentException, ArgumentNullException, PathTooLongException, DirectoryNotFoundException.
Although unlikely, it is possible that the permissions changed between your code checking that access is allowed and actually trying to create the directory.
I want to continue my code when error comes up , but i dont know how ...
here's my code :
foreach(string path in Directory.GetDirectories(#"C:\", "*.*", SearchOption.AllDirectories)
{
Console.WriteLine(path);
}
And the error comes on foreach(string path in Directory.GetDirectories(#"C:\", "*.*", SearchOption.AllDirectories) and i don't know how to continue this loop
and the error :
Unauthorized access
And even i run my code as Administrator this error comes up again
Thanks,
The best is to use recursive search and not using SearchOption.AllDirectories, but rather SearchOption.TopDirectoryOnly
If you use SearchOption.AllDirectories, one access violation will break your entire loop even before any file/directory is processed. But if you use SearchOption.TopDirectoryOnly, you only skip what is inaccessible.
Thus, to do it, you can create a method which receives a directory path as input. And in that method, if the input directory have child directory(ies) (see Directory.GetDirectories(string path) method, you call the method again for each child directory (recursive call) before you process all the files in the directory. Else, get the files (see Directory.GetFiles) in the directory and process them immediately.
Then for the method above, one way is to prevent the code crash when you cannot access certain file/directory is by using try-catch block for each child directory reading and file reading. This way, if one file/folder cannot be accessed, your code will still be running, finding the processing the next file/directory.
Alternatively, you can use Directory.GetAccessControl() per child directory check to see if you have an access to a Directory before hand (this option is rather hard though).
Edit (code added):
Something like this will do:
public static List<string> GetAllAccessibleDirectories(string path, string searchPattern) {
List<string> dirPathList = new List<string>();
try {
List<string> childDirPathList = Directory.GetDirectories(path, searchPattern, SearchOption.TopDirectoryOnly).ToList(); //use TopDirectoryOnly
if (childDirPathList == null || childDirPathList.Count <= 0) //this directory has no child
return null;
foreach (string childDirPath in childDirPathList) { //foreach child directory, do recursive search
dirPathList.Add(childDirPath); //add the path
List<string> grandChildDirPath = GetAllAccessibleDirectories(childDirPath, searchPattern);
if (grandChildDirPath != null && grandChildDirPath.Count > 0) //this child directory has children and nothing has gone wrong
dirPathList.AddRange(grandChildDirPath.ToArray()); //add the grandchildren to the list
}
return dirPathList; //return the whole list found at this level
} catch {
return null; //something has gone wrong, return null
}
}
And to call it, you can do something like this
string rootpath = #"C:\DummyRootFolder";
List<string> dirList = GetAllAccessibleDirectories(rootpath, "*.*"); //you get all accessible directories here
In the dirList you will get all the directories that you search for, and if there is access violation along the way, it will only affects sub-directories search due to the try-catch block.
Note that the rootpath is excluded in the method. But if you want to add it to the list too, you could simply do
dirList.Insert(0, path); //do this after you get dirList
There are also more complicated ways of doing this by using Directory.GetAccessControl and PermissionSet
Hope it may clarify.
According to the documentation, you should look at EnumerateDirectories for performance reasons:
https://msdn.microsoft.com/en-us/library/c1sez4sc(v=vs.110).aspx
Also, it appears that this question has already been answered before:
Directory.EnumerateFiles => UnauthorizedAccessException
Hope this helps!
How about this:
foreach (string path in Directory.GetDirectories(#"C:\", "*.*", SearchOption.AllDirectories)) {
try {
Console.WriteLine(path);
} catch (Exception ex) {
Console.WriteLine("Unable to access directories in path: " + path);
}
}
I try to write a console app C# to move my etxt files to another folder.
The functions just copies certain .txt files from folder A to folder AA
string source = "C:\\A\\ResultClassA.txt";
File.Move(Source, "C:\\AA");
But its always giving this error message:
Access to the path is denied.
Troubleshooting tips:
Make sure you have sufficient privileges to access this resource.
If you are attempting to access a file, make sure it is not ReadOnly.
Get general help for this exception.
Do i really need to set my folder A and folder B to "NOT ReadOnly" attribute before "File.move" code are execuse? and set to read only back after success moved?
Thanks.
By Hero .
You need to specify the full path and make sure the path C:\AA exists
string source = "C:\\A\\ResultClassA.txt";
File.Move(Source, "C:\\AA\\ResultClassA.txt");
See here for good sample
using System;
using System.IO;
class Test
{
public static void Main()
{
string path = #"c:\temp\MyTest.txt";
string path2 = #"c:\temp2\MyTest.txt";
try
{
if (!File.Exists(path))
{
// This statement ensures that the file is created,
// but the handle is not kept.
using (FileStream fs = File.Create(path)) {}
}
// Ensure that the target does not exist.
if (File.Exists(path2))
File.Delete(path2);
// Move the file.
File.Move(path, path2);
Console.WriteLine("{0} was moved to {1}.", path, path2);
// See if the original exists now.
if (File.Exists(path))
{
Console.WriteLine("The original file still exists, which is unexpected.");
}
else
{
Console.WriteLine("The original file no longer exists, which is expected.");
}
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
}
}
Hero, you are moving from a file name to a folder name, try to specify a file name with extension inside the C:\AA folder.
does AA exist already on C ?
I have written a code to move a file as follows
private void Move_Click(object sender, EventArgs e)
{
string strOrgpath = string.Empty, strNewpath = string.Empty;
strOrgpath = tvwACH.SelectedNode.ToString();
string strPath = strOrgpath.Substring(10);
FolderBrowserDialog folderborwser1 = new FolderBrowserDialog();
if (folderborwser1.ShowDialog() == DialogResult.OK)
{
try
{
strNewpath = folderborwser1.SelectedPath;
File.Move(strPath, strNewpath);
}
catch (Exception ex)
{
}
}
}
But i am getting the exception as i mentioned can any one tell why and some times i am getting the error as access to the path is denied
Make sure your substring call returns the correct result. If possible, use static methods from the Path class instead. Take a look at the MSDN page for File.Move and pay attention to what parameters are expected -- you should provide two valid full file names (e.g. C:\Blah\myFile.txt).
"Access denied" error message might happen if the user picks a folder they don't have write access to in the folder browser dialog. That's a scenario you'll have to handle in your code, perhaps by catching the UnauthorizedAccessException.
Update: the destination file should also point to a filename. So you'll need to do something like this:
var origFileName = Path.GetFileName(strPath);
strNewpath = Path.Combine(folderborwser1.SelectedPath, origFileName);
File.Move(strPath, strNewpath);
Without seeing the values that are being used in your application at run-time, I'm guessing tvwACH.SelecteNode.ToString() or strOrgpath.Substring(10) is not a valid File System path.
You should Debug your application and set a breakpoint to see what those values are (and post them if it's not obvious what your problem is at that point).
Imagine I wish to create (or overwrite) the following file :- C:\Temp\Bar\Foo\Test.txt
Using the File.Create(..) method, this can do it.
BUT, if I don't have either one of the following folders (from that example path, above)
Temp
Bar
Foo
then I get an DirectoryNotFoundException thrown.
So .. given a path, how can we recursively create all the folders necessary to create the file .. for that path? If Temp or Bar folders exists, but Foo doesn't... then that is created also.
For simplicity, lets assume there's no Security concerns -- all permissions are fine, etc.
To summarize what has been commented in other answers:
//path = #"C:\Temp\Bar\Foo\Test.txt";
Directory.CreateDirectory(Path.GetDirectoryName(path));
Directory.CreateDirectory will create the directories recursively and if the directory already exist it will return without an error.
If there happened to be a file Foo at C:\Temp\Bar\Foo an exception will be thrown.
DirectoryInfo di = Directory.CreateDirectory(path);
Console.WriteLine("The directory was created successfully at {0}.",
Directory.GetCreationTime(path));
See this MSDN page.
Use Directory.CreateDirectory before you create the file. It creates the folder recursively for you.
. given a path, how can we recursively create all the folders necessary to create the file .. for that path
Creates all directories and subdirectories as specified by path.
Directory.CreateDirectory(path);
then you may create a file.
You will need to check both parts of the path (directory and filename) and create each if it does not exist.
Use File.Exists and Directory.Exists to find out whether they exist. Directory.CreateDirectory will create the whole path for you, so you only ever need to call that once if the directory does not exist, then simply create the file.
You should use Directory.CreateDirectory.
http://msdn.microsoft.com/en-us/library/54a0at6s.aspx
Assuming that your assembly/exe has FileIO permission is itself, well is not right. Your application may not run with admin rights. Its important to consider Code Access Security and requesting permissions
Sample code:
FileIOPermission f2 = new FileIOPermission(FileIOPermissionAccess.Read, "C:\\test_r");
f2.AddPathList(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, "C:\\example\\out.txt");
try
{
f2.Demand();
}
catch (SecurityException s)
{
Console.WriteLine(s.Message);
}
Understanding .NET Code Access Security
Is “Code Access Security” of any real world use?
You want Directory.CreateDirectory()
Here is a class I use (converted to C#) that if you pass it a source directory and a destination it will copy all of the files and sub-folders of that directory to your destination:
using System.IO;
public class copyTemplateFiles
{
public static bool Copy(string Source, string destination)
{
try {
string[] Files = null;
if (destination[destination.Length - 1] != Path.DirectorySeparatorChar) {
destination += Path.DirectorySeparatorChar;
}
if (!Directory.Exists(destination)) {
Directory.CreateDirectory(destination);
}
Files = Directory.GetFileSystemEntries(Source);
foreach (string Element in Files) {
// Sub directories
if (Directory.Exists(Element)) {
copyDirectory(Element, destination + Path.GetFileName(Element));
} else {
// Files in directory
File.Copy(Element, destination + Path.GetFileName(Element), true);
}
}
} catch (Exception ex) {
return false;
}
return true;
}
private static void copyDirectory(string Source, string destination)
{
string[] Files = null;
if (destination[destination.Length - 1] != Path.DirectorySeparatorChar) {
destination += Path.DirectorySeparatorChar;
}
if (!Directory.Exists(destination)) {
Directory.CreateDirectory(destination);
}
Files = Directory.GetFileSystemEntries(Source);
foreach (string Element in Files) {
// Sub directories
if (Directory.Exists(Element)) {
copyDirectory(Element, destination + Path.GetFileName(Element));
} else {
// Files in directory
File.Copy(Element, destination + Path.GetFileName(Element), true);
}
}
}
}
Following code will create directories (if not exists) & then copy files.
// using System.IO;
// for ex. if you want to copy files from D:\A\ to D:\B\
foreach (var f in Directory.GetFiles(#"D:\A\", "*.*", SearchOption.AllDirectories))
{
var fi = new FileInfo(f);
var di = new DirectoryInfo(fi.DirectoryName);
// you can filter files here
if (fi.Name.Contains("FILTER")
{
if (!Directory.Exists(di.FullName.Replace("A", "B"))
{
Directory.CreateDirectory(di.FullName.Replace("A", "B"));
File.Copy(fi.FullName, fi.FullName.Replace("A", "B"));
}
}
}