I want to copy the file c:\a1\b2\c3\foo.txt to d:\a1\b2\c3\foo.txt. The subdirectories don't exist on the D drive, and if I try to do a direct CopyTo() I'll get an IO exception.
I haven't been able to find any built-in c# function that does the dirty work of creating the missing directories. So I wrote this:
FileInfo file = new FileInfo(#"c:\a1\b2\c3\foo.txt");
DirectoryInfo destDir = new DirectoryInfo(file.DirectoryName.Replace("c:", "d:");
if (!destDir.Exists) // false
CreateDirectory(destDir, null);
file.CopyTo(file.FullName.Replace("c:", "d:"), true);
private void CreateDirectory(DirectoryInfo endDir, Stack<DirectoryInfo> trail)
{
if (trail == null)
{
trail = new Stack<DirectoryInfo>();
trail.Push(endDir);
}
// remove last directory - c:\a1\b2\c3, c:\a1\b2, c:\a1
Match theMatch = Regex.Match(endDir.FullName, #".*(?=\\\w*\Z)");
DirectoryInfo checkDir = new DirectoryInfo(theMatch.ToString());
if (!checkDir.Exists)
{
trail.Push(checkDir);
CreateDirectory(checkDir, trail);
}
else
foreach (DirectoryInfo dir in trail)
Directory.CreateDirectory(dir.FullName);
}
That's pretty involved, and as they like to say on late-night informercials, "There's got to be a better way!"
Question: how would I make the function above move efficient? And am I missing a built-in method that already does everything I'm doing the hard way?
Directory.CreateDirectory(#"c:\foo\bar\baz");
Documented as creating all required directories, and works for me.
Any and all directories specified in
path are created, unless they already
exist or unless some part of path is
invalid. The path parameter specifies
a directory path, not a file path. If
the directory already exists, this
method does nothing.
Or you can just use Directory.CreateDirectory() directly, since it already creates all the intermediate paths.
Strange, I am working with CopyTo and it creates all the subdirectories automatically in the destination location.
My code is as simple as can be:
// file is FileInfo and target is DirectoryInfo
file.CopyTo(target);
A DirectoryInfo instance can create its own path with all the checking you want via destDir.Create():
FileInfo file = new FileInfo(#"c:\a1\b2\c3\foo.txt");
DirectoryInfo destDir = new DirectoryInfo(file.DirectoryName.Replace("c:", "d:");
destDir.Create(); // <-- makes it if it doesn't exist, otherwise noop
var newPath =
Path.Combine(destDir.FullName, Path.GetFileName(file)); // <-- just to be safe...
file.CopyTo(newPath, true);
Found this out here: https://stackoverflow.com/a/2955425/1037948
Related
I have a C# console application that sends Excel spreadsheet attachments through email.
I have given the file path in App.config. While trying to find the file, the code looks at proper location. But when trying to attach the file inside the foreach statement, it is looking in code's bin folder.
What am I doing wrong here?
DirectoryInfo dir1 = new DirectoryInfo(ConfigurationManager.AppSettings.Get("FilePath"));
FileInfo[] folderFiles = null;
folderFiles = dir1.GetFiles();
foreach (FileInfo aFile in folderFiles)
{
message.Attachments.Add(new Attachment(aFile.Name));
}
You need to use aFile.FullName (includes the full path) rather than aFile.Name (only the filename). If a command is not doing what you expect, you should check the documentation.
Alternatively, you could make it simpler:
string dir1 = ConfigurationManager.AppSettings.Get("FilePath");
foreach(string aFile in Directory.EnumerateFiles(dir1))
{
message.Attachments.Add(new Attachment(aFile));
}
as Directory.EnumerateFiles simply returns the full filenames and you would have to think about not doing so (e.g. by using Path.GetFileName) to do otherwise.
This should be very simple but I'm not sure what's wrong. I'm trying to delete all the files in a folder using File.Delete.
This is what I have so far:
DirectoryInfo ImageFolder = new DirectoryInfo(Program.FolderPath + #"\Images");
foreach (var File in ImageFolder.GetFiles())
{
File.Delete(File.FullName);
}
Then the ".Delete" becomes underlined and says no overload for method delete takes 1 argument.
Any help is appreciated.
What you're seeing is called Namespace Ambiguity.
In your own code or a reference DLL you probably have a method called Delete in a Class called File that doesn't support a single string parameter.
To fix the problem fully qualify File.Delete with System.IO, eg:
System.IO.File.Delete
To delete folder full of file use:
Directory.Delete(string directoryName, bool recursive);
https://msdn.microsoft.com/en-us/library/fxeahc5f(v=vs.110).aspx
Or from your code above, use:
DirectoryInfo ImageFolder = new DirectoryInfo(Program.FolderPath + #"\Images");
foreach (var fileInfo in ImageFolder.GetFiles())
{
fileInfo.Delete(); //this is FileInfo.Delete
// or
// File.Delete(fileInfo.FullName);
// dont use reserve "File" as your variable name
}
Remember, you are calling FileInfo, not File
You have to change the naming of the variable:
DirectoryInfo ImageFolder = new DirectoryInfo(Program.FolderPath + #"\Images");
foreach (var file in ImageFolder.GetFiles())
{
File.Delete(file.FullName);
}
I have a list of directories - these folders are all websites - and I need to write some code to traverse down each one of these directories until I find the index.html file. When I find index.html, I need to write the entire path out to a text file. I know how to do basic file I/O, such as writing data to a file, but what I'm getting hung up on is how to traverse down each directory until I hit a certain file, then capture that entire path, then continue on to the next folder/directory. I'm not sure where to start and I was hoping I could find some guidance from you all.
There is a function that can do that : Directory.GetFiles Method (String, String, SearchOption)
Returns the names of files (including their paths) that match the specified search pattern in the specified directory, using a value to determine whether to search subdirectories.
If you just want to find the very first instance of a file with a particular name and stop searching immediately when you find it, this is the most efficient approach.
It uses the SearchOption.AllDirectories option to tell it to recursively descend the directories for you.
string rootPath = "X:\\MyRoot";
string targetPattern = "index.html";
string fullPath = Directory
.EnumerateFiles(rootPath, targetPattern, SearchOption.AllDirectories)
.FirstOrDefault();
if (fullPath != null)
Console.WriteLine("Found " + fullPath);
else
Console.WriteLine("Not found");
(Note that if you use Directory.GetFiles() it will iterate over all possible folders, even if it has already found an instance of the target file, whereas EnumerateFiles() allows you to stop iterating as soon as the file is found.)
This uses Linq's FirstOrDefault() to stop iterating as soon as a file is found, so you'll have to add using System.Linq;
Note that FirstOrDefault() will return null (for strings, as in this example) when there are no items in the sequence.
One important thing to be aware of is that both Directory.EnumerateFiles() and Directory.GetFiles() will throw exceptions if you attempt to access directories that you aren't allowed to (for example, if you start at the root of C:\, it could attempt to access C:\$Recycle.Bin which will cause an exception).
If you have many directories and files may enumerate them; it could be convenient if you want to exclude some directories:
public static String FindFileDeep(String path, String fileName) {
foreach(String file in Directory.EnumerateFiles(path))
if (String.Equals(Path.GetFileName(file), fileName, StringComparison.OrdinalIgnoreCase))
return file;
foreach (var dir in Directory.EnumerateDirectories(path)) {
// You can exclude some directories here:
// if (...) continue;
String result = FindIndexHtml(dir);
if (!String.IsNullOrEmpty(result))
return result;
}
return null;
}
...
String indexHtml = FindFileDeep(#"C:\MyFiles", "index.html");
Create a method that gets the contents of a directory (DirectoryInfo class) that is passed as a parameters.
Cycle through each of the .GetFiles() of the DirectoryInfo to find the flie.
Then, if need be, use the .GetDirectories() list and cycle through them re-calling the same function with the found directory name.
Disclaimer: Uncompiplied/untests - Prototype...
static void Main(string[] args)
{
FileInfo fi = FindFile("index.html", new DirectoryInfo("C:\\"));
}
static FileInfo FindFile(string Name, DirectoryInfo di)
{
FileInfo fiFound = null;
// Try and find it in this directory
FileInfo[] fiList = di.GetFiles("index.html");
if (fiList.Length == 0)
{
foreach (DirectoryInfo diCycle in di.GetDirectories())
{
fiFound = FindFile(Name, diCycle);
}
}
else
{
fiFound = fiList.First();
}
return (fiFound);
}
i want to create C# mass file renamer, here is my UI
i have created tes folder, inside of tes there's a file which is 1.txt.
i want to create my program to add prefix and suffix to the files, so 1.txt will become
prefix1suffix
but then i got an error
it's said file already exist though there's only one file on tes folder, which is 1.txt how do i make it work ? where's the error comes from ?
i have tried the following code
private void Rename(string prefix, string filepath, string suffix)
{
//i don't use prefix suffix yet to make sure if my function works
DirectoryInfo d = new DirectoryInfo(filepath);
FileInfo[] file = d.GetFiles();
try
{
foreach (FileInfo f in file )
{
File.Move(f.FullName,"stackoverflow");
}
}
catch (Exception e)
{
cmd.cetakGagal(e.ToString(), title);
}
cmd.cetakSukses("Rename Success", title);
}
and it returns same error as the second picture above.
the following picture is tes folder, there's nothing in tes folder except 1.txt
You are calling File.Move() with a full path for your sourceFileName and a relative path for your destFileName. The relative file path is relative to the current working directory and not to the source file path. I expect that a stackoverflow file exists in the current working directory, most likely created the first time you ran this code.
your File.Move is changing them all to StackOverflow not using the prefix and suffix. If you only have one file in the directory it shouldn't be an issue. Are you sure there is only 1 file?
public static void Move(
string sourceFileName,
string destFileName
)
Looking at this answer might be the clue as you are specifying relative path for the destination file. To obtain the current working directory, see GetCurrentDirectory
The sourceFileName and destFileName arguments are permitted to specify
relative or absolute path information. Relative path information is
interpreted as relative to the current working directory.
You should change
File.Move(f.FullName,"stackoverflow");
to
string fileName = f.Name.Replace(f.Extenstion,string.Empty);
string newFileName = string.Format("{0}{1}{2}",prefix,fileName,suffix);
string newFileWithPath = Path.Combine(f.Directory,newFileName);
if (!File.Exists(newFileWithPath))
{
File.Move(f.FullName,newFileWithPath);
}
The code above will give you that error since, after the first run through, "stackoverflow" exists as a file. Make sure that you check if the destination file exists (using File.Exists) before calling File.Move.
Since your goal is renaming, I would suggest using a test folder filled with files rather than using a piecemeal approach. See if something like this helps:
private void Rename(string prefix, string filepath, string suffix)
{
//i don't use prefix suffix yet to make sure if my function works
DirectoryInfo d = new DirectoryInfo(filepath);
FileInfo[] file = d.GetFiles();
try
{
foreach (FileInfo f in file )
{
f.MoveTo(#filepath + #"\" + prefix + f.Name.Insert(f.Name.LastIndexOf('.'),suffix));
}
}
catch (Exception e)
{
cmd.cetakGagal(e.ToString(), title);
}
cmd.cetakSukses("Rename Success", title);
}
on a side note using a listview to display the filenames and the changes before they're committed will help prevent unwanted changes.
I need to Copy folder C:\FromFolder to C:\ToFolder
Below is code that will CUT my FromFolder and then will create my ToFolder.
So my FromFolder will be gone and all the items will be in the newly created folder called ToFolder
System.IO.Directory.Move(#"C:\FromFolder ", #"C:\ToFolder");
But i just want to Copy the files in FromFolder to ToFolder.
For some reason there is no System.IO.Directory.Copy???
How this is done using a batch file - Very easy
xcopy C:\FromFolder C:\ToFolder
Regards
Etienne
This link provides a nice example.
http://msdn.microsoft.com/en-us/library/cc148994.aspx
Here is a snippet
// To copy all the files in one directory to another directory.
// Get the files in the source folder. (To recursively iterate through
// all subfolders under the current directory, see
// "How to: Iterate Through a Directory Tree.")
// Note: Check for target path was performed previously
// in this code example.
if (System.IO.Directory.Exists(sourcePath))
{
string[] files = System.IO.Directory.GetFiles(sourcePath);
// Copy the files and overwrite destination files if they already exist.
foreach (string s in files)
{
// Use static Path methods to extract only the file name from the path.
fileName = System.IO.Path.GetFileName(s);
destFile = System.IO.Path.Combine(targetPath, fileName);
System.IO.File.Copy(s, destFile, true);
}
}
there is a file copy.
Recreate folder and copy all the files from original directory to the new one
example
static void Main(string[] args)
{
DirectoryInfo sourceDir = new DirectoryInfo("c:\\a");
DirectoryInfo destinationDir = new DirectoryInfo("c:\\b");
CopyDirectory(sourceDir, destinationDir);
}
static void CopyDirectory(DirectoryInfo source, DirectoryInfo destination)
{
if (!destination.Exists)
{
destination.Create();
}
// Copy all files.
FileInfo[] files = source.GetFiles();
foreach (FileInfo file in files)
{
file.CopyTo(Path.Combine(destination.FullName,
file.Name));
}
// Process subdirectories.
DirectoryInfo[] dirs = source.GetDirectories();
foreach (DirectoryInfo dir in dirs)
{
// Get destination directory.
string destinationDir = Path.Combine(destination.FullName, dir.Name);
// Call CopyDirectory() recursively.
CopyDirectory(dir, new DirectoryInfo(destinationDir));
}
}
Copying directories (correctly) is actually a rather complex task especially if you take into account advanced filesystem techniques like junctions and hard links. Your best bet is to use an API that supports it. If you aren't afraid of a little P/Invoke, SHFileOperation in shell32 is your best bet. Another alternative would be to use the Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory method in the Microsoft.VisualBasic assembly (even if you aren't using VB).
yes you are right.
http://msdn.microsoft.com/en-us/library/system.io.directoryinfo.aspx
has provided copy function ..
or you can use another function
http://msdn.microsoft.com/en-us/library/ms127960.aspx
You'll need to create a new directory from scratch then loop through all the files in the source directory and copy them over.
string[] files = Directory.GetFiles(GlobalVariables.mstrReadsWellinPath);
foreach(string s in files)
{
fileName=Path.GetFileName(s);
destFile = Path.Combine(DestinationPath, fileName);
File.Copy(s, destFile);
}
I leave creating the destination directory to you :-)
You're right. There is no Directory.Copy method. It would be a very powerful method, but also a dangerous one, for the unsuspecting developer. Copying a folder can potentionaly be a very time consuming operation, while moving one (on the same drive) is not.
I guess Microsoft thought it would make sence to copy file by file, so you can then show some kind of progress information. You could iterate trough the files in a directory by creating an instance of DirectoryInfo and then calling GetFiles(). To also include subdirectories you can also call GetDirectories() and enumerate trough these with a recursive method.
A simple function that copies the entire contents of the source folder to the destination folder and creates the destination folder if it doesn't exist
class Utils
{
internal static void copy_dir(string source, string dest)
{
if (String.IsNullOrEmpty(source) || String.IsNullOrEmpty(dest)) return;
Directory.CreateDirectory(dest);
foreach (string fn in Directory.GetFiles(source))
{
File.Copy(fn, Path.Combine(dest, Path.GetFileName(fn)), true);
}
foreach (string dir_fn in Directory.GetDirectories(source))
{
copy_dir(dir_fn, Path.Combine(dest, Path.GetFileName(dir_fn)));
}
}
}
This article provides an alogirthm to copy recursively some folder and all its content
From the article :
Sadly there is no built-in function in System.IO that will copy a folder and its contents. Following is a simple recursive algorithm that copies a folder, its sub-folders and files, creating the destination folder if needed. For simplicity, there is no error handling; an exception will throw if anything goes wrong, such as null or invalid paths or if the destination files already exist.
Good luck!
My version of DirectoryInfo.CopyTo using extension.
public static class DirectoryInfoEx {
public static void CopyTo(this DirectoryInfo source, DirectoryInfo target) {
if (source.FullName.ToLower() == target.FullName.ToLower())
return;
if (!target.Exists)
target.Create();
foreach (FileInfo f in source.GetFiles()) {
FileInfo newFile = new FileInfo(Path.Combine(target.FullName, f.Name));
f.CopyTo(newFile.FullName, true);
}
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories()) {
DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
diSourceSubDir.CopyTo(nextTargetSubDir);
}
}
}
And use like that...
DirectoryInfo d = new DirectoryInfo("C:\Docs");
d.CopyTo(new DirectoryInfo("C:\New"));