I believed this to be really simple but somehow i am making a mistake.I am trying to copy one folder to another location
Directory.Move(SourcePath, Destinationpath )
This expression is failing. The exception thrown is "cannot create file that already exists"
Well, you say you want to "copy one folder to another".
Directory.Move(), doesn't copy: as its name implies, it moves a directory. Take at look at the documentation on how to copy files:
.Net 4.0 (see here for an asynchronous approach)
.Net 4.5 (see here for an asynchronous approach)
The Move call is failing because a directory or file in the move operation exists at the specified location (as the exception noted). In order to fix this you need to ensure that no file or directory exists at the destination. The easiest way is to first delete that path
Do not run this function unless you are OK with unconditionally deleting data at DestinationPath.
static void MyMove(string sourcePath, string destPath) {
try {
Directory.Delete(destPath, recursive: true);
} catch {
// Don't care if this fails. If the file didn't exist, great, if the
// file can't be deleted will still get an error in Move. Just try
// Move at this point
}
Directory.Move(sourcePath, destPath);
}
Related
I've got a folder:
c:\test
I'm trying this code:
File.Move(#"c:\test\SomeFile.txt", #"c:\test\Test");
I get exception:
File already exists
The output directory definitely exists and the input file is there.
What you need is:
if (!File.Exists(#"c:\test\Test\SomeFile.txt")) {
File.Move(#"c:\test\SomeFile.txt", #"c:\test\Test\SomeFile.txt");
}
or
if (File.Exists(#"c:\test\Test\SomeFile.txt")) {
File.Delete(#"c:\test\Test\SomeFile.txt");
}
File.Move(#"c:\test\SomeFile.txt", #"c:\test\Test\SomeFile.txt");
This will either:
If the file doesn't exist at the destination location, successfully move the file, or;
If the file does exist at the destination location, delete it, then move the file.
Edit: I should clarify my answer, even though it's the most upvoted!
The second parameter of File.Move should be the destination file - not a folder. You are specifying the second parameter as the destination folder, not the destination filename - which is what File.Move requires.
So, your second parameter should be c:\test\Test\SomeFile.txt.
You need to move it to another file (rather than a folder), this can also be used to rename.
Move:
File.Move(#"c:\test\SomeFile.txt", #"c:\test\Test\SomeFile.txt");
Rename:
File.Move(#"c:\test\SomeFile.txt", #"c:\test\SomeFile2.txt");
The reason it says "File already exists" in your example, is because C:\test\Test tries to create a file Test without an extension, but cannot do so as a folder already exists with the same name.
Personally I prefer this method.
This will overwrite the file on the destination, removes the source file and also prevent removing the source file when the copy fails.
string source = #"c:\test\SomeFile.txt";
string destination = #"c:\test\test\SomeFile.txt";
try
{
File.Copy(source, destination, true);
File.Delete(source);
}
catch
{
//some error handling
}
You can do a P/Invoke to MoveFileEx() - pass 11 for flags (MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
static extern bool MoveFileEx(string existingFileName, string newFileName, int flags);
Or, you can just call
Microsoft.VisualBasic.FileIO.FileSystem.MoveFile(existingFileName, newFileName, true);
after adding Microsoft.VisualBasic as a reference.
With C# on .Net Core 3.0 and beyond, there is now a third boolean parameter:
In .NET Core 3.0 and later versions, you can call Move(String, String, Boolean) setting the parameter overwrite to true, which will replace the file if it exists.
Source: Microsoft Docs
For all other versions of .Net, this answer is the best. Copy with Overwrite, then delete the source file. This is better because it makes it an atomic operation. (I have attempted to update the MS Docs with this)
If file really exists and you want to replace it use below code:
string file = "c:\test\SomeFile.txt"
string moveTo = "c:\test\test\SomeFile.txt"
if (File.Exists(moveTo))
{
File.Delete(moveTo);
}
File.Move(file, moveTo);
According to the docs for File.Move there is no "overwrite if exists" parameter. You tried to specify the destination folder, but you have to give the full file specification.
Reading the docs again ("providing the option to specify a new file name"), I think, adding a backslash to the destination folder spec may work.
Try Microsoft.VisualBasic.FileIO.FileSystem.MoveFile(Source, Destination, True). The last parameter is Overwrite switch, which System.IO.File.Move doesn't have.
If you don't have the option to delete the already existing file in the new location, but still need to move and delete from the original location, this renaming trick might work:
string newFileLocation = #"c:\test\Test\SomeFile.txt";
while (File.Exists(newFileLocation)) {
newFileLocation = newFileLocation.Split('.')[0] + "_copy." + newFileLocation.Split('.')[1];
}
File.Move(#"c:\test\SomeFile.txt", newFileLocation);
This assumes the only '.' in the file name is before the extension.
It splits the file in two before the extension, attaches "_copy." in between.
This lets you move the file, but creates a copy if the file already exists or a copy of the copy already exists, or a copy of the copy of the copy exists... ;)
This is similar with this question but with one more requirement:
Since the deletion of files can fail for whatever reasons. So I want the operation to be "transacted" which mean the whole operation either success in total, or fail and do not change anything at all.
In general this will be very very hard and I can't see any possibility to recover when the physical hard drive suddenly broken. So a weakened clause would be: if it success, we finished. Otherwise if fail, restore everything to the original state when possible.
Some kind of errors I could think of would be:
Access violation. You simply don't allowed to delete some files or folders. This is the case that I wanted to handle the most.
File/folder was used by somebody else and so it is "locked". In Linux this is not a problem but in Windows it is. This is also to be handled.
If it is a network folder there could be network issues. The recover can be hard or impossible. I would not expect this kind of error to be properly handled.
Hardware failure. I don't think any recover can happen here.
Scenario
You have a software that can export its internal data. The result is in a folder and with sub-folder names timestamped.
Now if the user specified a folder that is not empty (probably a previous output folder), the software will create new sub-folders on top of it, which is a mass. So you want to ensure the folder is empty before performing the export.
You can easily detect the folder emptiness and alert the user if not. But if the user say "go ahead and do it" you should do something then. Now, what if you were deleted some of the files and failed on others?
Going ahead in this case is just creating worse mass. At the same time the user would not expect a damaged folder without getting anything working. So it is better to either give them a fully working output or does not change the previous output at all.
As per comments, I'll give you the pseudocode for the process you can follow writing the code:
Clear contents of cache folder if any files exist (they shouldn't)
Copy contents of destination folder to cache folder
Try
While files exist, iterate
Delete file
End While
Catch
While files exist in cache, iterate
If file does not exist in destination folder
Move file from cache to destination
else
Delete file from cache
end If
End While
End Try
By following the guidelines given in the comments, I came up with this solution.
The following code will attempt to move everything to a temporary folder inside the given folder. If success, it returns True. If failed, the catch block will then try to move everything back and return a False. In either case, the finally block will remove the temporary folder recursively.
public static bool EmptyFolderTransactionaly(string folder)
{
var directoryInfo = new DirectoryInfo(folder);
var tmpDir = Directory.CreateDirectory(Path.Combine(folder, Path.GetFileName(Path.GetTempFileName())));
try
{
foreach (var e in directoryInfo.EnumerateFiles())
{
e.MoveTo(Path.Combine(tmpDir.FullName, e.Name));
}
foreach (var e in directoryInfo.EnumerateDirectories().Where(e => e.Name!=tmpDir.Name))
{
e.MoveTo(Path.Combine(tmpDir.FullName, e.Name));
}
return true;
}
catch
{
foreach (var e in tmpDir.EnumerateDirectories())
{
e.MoveTo(Path.Combine(directoryInfo.FullName, e.Name));
}
foreach (var e in tmpDir.EnumerateFiles())
{
e.MoveTo(Path.Combine(directoryInfo.FullName, e.Name));
}
return false;
}
finally
{
tmpDir.Delete(true);
}
}
Let me know if you see any risks in the code.
I have the following code which copies a file to a specific folder and then renames it.
When a file with that name already exists I get the following exception:
Cannot create a file when that file already exists
Is there a way to overwrite the file and rename it? or I should delete the old one and then change the name?
Here is my code:
File.Copy(FileLocation, NewFileLocation, true);
//Rename:
File.Move(Path.Combine(NewFileLocation, fileName), Path.Combine(NewFileLocation, "File.txt"));
Try to use only:
if (File.Exists("newfilename"))
{
System.IO.File.Delete("newfilename");
}
System.IO.File.Move("oldfilename", "newfilename");
One simple option is to delete the file if it exists:
if (System.IO.File.Exists(newFile)) System.IO.File.Delete(newFile);
System.IO.File.Move(oldFile, newFile);
Something like that should work.
You're correct, File.Move will throw an IOException if/when the filename already exists. So, to overcome that you can perform a quick check before the move. e.g.
if (File.Exists(destinationFilename))
{
File.Delete(destinationFilename);
}
File.Move(sourceFilename, destinationFilename);
You should use File.Exists rather than letting the Exception throw. You can then handle if the file should be overwrote or renamed.
Step 1 : as a first step identify wether the file exists or not before copying the file.
using File.Exists() method
Step 2: if the file already exists with same name then delete the existing file using File.Delete() method
Step 3: now copy the File into the new Location using File.Copy() method.
Step 4: Rename the newly copied file.
Try This:
string NewFilePath = Path.Combine(NewFileLocation, fileName);
if(File.Exists(NewFilePath))
{
File.Delete(NewFilePath);
}
//Now copy the file first
File.Copy(FileLocation, NewFileLocation, true);
//Now Rename the File
File.Move(NewFilePath, Path.Combine(NewFileLocation, "File.txt"));
I always use MoveFileEx with the flag MOVEFILE_REPLACE_EXISTING.
Limitations:
It needs to use PInvoke, so it means your code will only work on the Windows platform.
This flag MOVEFILE_REPLACE_EXISTING only work with File(Doesn't work with Folder)
If lpNewFileName or lpExistingFileName name a directory and lpExistingFileName exists, an error is reported.
I created a zip file/folder with DotNetZip. I'm trying to move that file from the original directory/folder to another, e.g. My Documents. So far I have done the following, but it gives me an error saying that it could not find part of the path.
private static void Move()
{
try
{
Directory.Move(#"Debug\Settings.zip", IO.Paths.Enviroment.MyDocuments);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
UPDATE:
So I've played with it a bit and laughed not because I fixed it but because it's weird. I used both File.Move() and Directory.Move() and changed both.Move(#"Debug\Settings.zip",...); to both.Move(#"Settings.zip",...); and then get get an an error saying Cannot create a file when that file already exists.
While it may seem strange to use Directory.Move to move a file, (I'd use File.Move instead), Jean-Philippe Leclerc points out that it will work.
The problem is with the path Debug\Settings.zip:
All relative paths are relative to the working directory. By default the working directory is the folder in which the assembly (your program) is executed, and while debugging that is the bin\Debug subfolder of your project. So your path Debug\Settings.zip is expanded to a path like:
C:\..\MyProject\bin\Debug\Debug\Settings.zip
This is probably not what you meant. You meant just "Settings.zip".
The fact that it's a ZIP is irrelevant.
Use System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) to get your MyDocuments path.
could not find part of the path - The error seems like the Relative Path to your file Settings.Zip is not a valid path!
You need to use File.Move, Directory.Move will move the entire content of the Directory to different folder.
File.Move : Only moves the file to a specified location
private static void Move()
{
try
{
File.Move(#"Debug\Settings.zip", System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Fixed! The issues were first the "Debug\Settings.zip" should have been "Settings.zip" or #"Settings.zip" and finally destination should not just be System.IO.File.Move(#"Settings.zip", System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop)); but System.IO.File.Move(#"Settings.zip", System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + #"\Settings.zip"); Basically, add the file name and the extension of the file at the end of the destination string.
I've got a folder:
c:\test
I'm trying this code:
File.Move(#"c:\test\SomeFile.txt", #"c:\test\Test");
I get exception:
File already exists
The output directory definitely exists and the input file is there.
What you need is:
if (!File.Exists(#"c:\test\Test\SomeFile.txt")) {
File.Move(#"c:\test\SomeFile.txt", #"c:\test\Test\SomeFile.txt");
}
or
if (File.Exists(#"c:\test\Test\SomeFile.txt")) {
File.Delete(#"c:\test\Test\SomeFile.txt");
}
File.Move(#"c:\test\SomeFile.txt", #"c:\test\Test\SomeFile.txt");
This will either:
If the file doesn't exist at the destination location, successfully move the file, or;
If the file does exist at the destination location, delete it, then move the file.
Edit: I should clarify my answer, even though it's the most upvoted!
The second parameter of File.Move should be the destination file - not a folder. You are specifying the second parameter as the destination folder, not the destination filename - which is what File.Move requires.
So, your second parameter should be c:\test\Test\SomeFile.txt.
You need to move it to another file (rather than a folder), this can also be used to rename.
Move:
File.Move(#"c:\test\SomeFile.txt", #"c:\test\Test\SomeFile.txt");
Rename:
File.Move(#"c:\test\SomeFile.txt", #"c:\test\SomeFile2.txt");
The reason it says "File already exists" in your example, is because C:\test\Test tries to create a file Test without an extension, but cannot do so as a folder already exists with the same name.
Personally I prefer this method.
This will overwrite the file on the destination, removes the source file and also prevent removing the source file when the copy fails.
string source = #"c:\test\SomeFile.txt";
string destination = #"c:\test\test\SomeFile.txt";
try
{
File.Copy(source, destination, true);
File.Delete(source);
}
catch
{
//some error handling
}
You can do a P/Invoke to MoveFileEx() - pass 11 for flags (MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
static extern bool MoveFileEx(string existingFileName, string newFileName, int flags);
Or, you can just call
Microsoft.VisualBasic.FileIO.FileSystem.MoveFile(existingFileName, newFileName, true);
after adding Microsoft.VisualBasic as a reference.
With C# on .Net Core 3.0 and beyond, there is now a third boolean parameter:
In .NET Core 3.0 and later versions, you can call Move(String, String, Boolean) setting the parameter overwrite to true, which will replace the file if it exists.
Source: Microsoft Docs
For all other versions of .Net, this answer is the best. Copy with Overwrite, then delete the source file. This is better because it makes it an atomic operation. (I have attempted to update the MS Docs with this)
If file really exists and you want to replace it use below code:
string file = "c:\test\SomeFile.txt"
string moveTo = "c:\test\test\SomeFile.txt"
if (File.Exists(moveTo))
{
File.Delete(moveTo);
}
File.Move(file, moveTo);
According to the docs for File.Move there is no "overwrite if exists" parameter. You tried to specify the destination folder, but you have to give the full file specification.
Reading the docs again ("providing the option to specify a new file name"), I think, adding a backslash to the destination folder spec may work.
Try Microsoft.VisualBasic.FileIO.FileSystem.MoveFile(Source, Destination, True). The last parameter is Overwrite switch, which System.IO.File.Move doesn't have.
If you don't have the option to delete the already existing file in the new location, but still need to move and delete from the original location, this renaming trick might work:
string newFileLocation = #"c:\test\Test\SomeFile.txt";
while (File.Exists(newFileLocation)) {
newFileLocation = newFileLocation.Split('.')[0] + "_copy." + newFileLocation.Split('.')[1];
}
File.Move(#"c:\test\SomeFile.txt", newFileLocation);
This assumes the only '.' in the file name is before the extension.
It splits the file in two before the extension, attaches "_copy." in between.
This lets you move the file, but creates a copy if the file already exists or a copy of the copy already exists, or a copy of the copy of the copy exists... ;)