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
Related
I have one ZIP file named abc.ZIP
Inside ZIP folder structure is as below:
--abc
---pqr
----a
----b
----c
I want to extract this ZIP at D:/folder_name
But i want to extract only folder and its content named a,b,c. Also folder names are not fixed. I dont want to extract root folder abc and its child folder pqr.
I used following code but its not working:
using (ZipFile zipFile = ZipFile.Read(#"temp.zip"))
{
foreach (ZipEntry entry in zipFile.Entries)
{
entry.Extract(#"D:/folder_name");
}
}
The following should work, but I'm not sure, if it's the best option.
string rootPath = "abc/pqr/";
using (ZipFile zipFile = ZipFile.Read(#"abc.zip"))
{
foreach (ZipEntry entry in zipFile.Entries)
{
if (entry.FileName.StartsWith(rootPath) && entry.FileName.Length > rootPath.Length)
{
string path = Path.Combine(#"D:/folder_name", entry.FileName.Substring(rootPath.Length));
if (entry.IsDirectory)
{
Directory.CreateDirectory(path);
}
else
{
using (FileStream stream = new FileStream(path, FileMode.Create))
entry.Extract(stream);
}
}
}
}
Other option would be to extract the complete file in a temporary directory and move the sub directories to your target directory.
I am trying to zip together all folders and their contents into a zip file. From what I have researched (through StackOverflow and Microsoft), Directory.CreateDirectory(Path) should create the given directory. However, my ZipFile is showing up empty.
For example, I have a folder (C:\Users\smelmo\Desktop\test) with the subfolders (0001, 0002) in it. Within 0001 and 0002 are other documents. I am wanting to zip 0001 and 0002 together within the test folder. This is what I have so far:
// Open the directory of the target folder
using (ZipArchive archive = ZipFile.Open(strZipPath, ZipArchiveMode.Create))
{
// Grab each directory within the target folder
foreach (var directoryName in Directory.GetDirectories(strStartPath))
{
// Add each directory to the ZipFile
Directory.CreateDirectory(directoryName);
}
}
This does not produce anything. HOWEVER, I also have code that will grab ALL files within the subfolders and place them in the ZipFile.
// Open the directory of the target folder
using (ZipArchive archive = ZipFile.Open(strZipPath, ZipArchiveMode.Create))
{
// Grab each directory within the target folder
foreach (var directoryName in Directory.GetDirectories(strStartPath))
{
//Grab all files in each directory
foreach (var filePath in Directory.GetFiles(directoryName))
{
var fileName = Path.GetFileName(#filePath);
// Place each directory and its repsective files in the zip file
var entry = archive.CreateEntryFromFile(filePath, fileName);
}
}
}
But this does not place subfolders 0001 and 0002 in it, just the CONTENTS of 0001 and 0002. I am wanting 0001 and 0002 and their respective contents.
Edited:
If you are looking for more control, you can just create a function that adds files to a zip archive. You can then use recursion to add any subfolders and files.
First you can define a function that accepts a zip archive to add files to:
public void AddFolderToZip(ZipArchive archive, string rootPath, string path, bool recursive)
{
foreach (var filePath in Directory.GetFiles(path))
{
//Remove root path portion from file path, so entry is relative to root
string entryName = filePath.Replace(rootPath, "");
entryName = entryName.StartsWith("\\") ? entryName.Substring(1) : entryName;
var entry = archive.CreateEntryFromFile(filePath, entryName);
}
if (recursive)
{
foreach (var subPath in Directory.GetDirectories(path))
{
AddFolderToZip(archive, rootPath, subPath, recursive);
}
}
}
Then you can call it using the following code:
string strStartPath = #"C:\Test\zip";
string strZipPath = #"C:\Test\output.zip";
ZipArchive archive = ZipFile.Open(strZipPath, ZipArchiveMode.Create);
bool recursive = true;
foreach (var directoryPath in Directory.GetDirectories(strStartPath))
{
AddFolderToZip(archive, strStartPath, directoryPath, recursive);
}
archive.Dispose();
This code adds each directory it finds in a top level directory. And for each directory it finds, it will use recursion to add any subdirectories or files found within those.
I am trying to zip a folder using IonicZip library in C#. It is able to zip .txt, .exe, .pdf etc. in the folder, but not able to zip folder in folder.
It is able to zip MusicLogs.txt and Video.exe but cannot Music folder.Music folder contains some folder also. It doesnt see Music folder even while debugging. My code is :
string zipPath = #"C:\" + DateTime.Now.ToString("yyyy-MM-dd HH-mm") + ".zip"; // zipped file extracts here
string filename = #"E:\"; // the fodler which should be zipped. File must be exist
using (ZipFile zipFile = new ZipFile())
{
zipFile.Password = "asd";
zipFile.Encryption = EncryptionAlgorithm.PkzipWeak;
foreach (string file in Directory.GetFiles(filename)) // this foreach is for getting all files in a folder.
{
zipFile.AddFile(file, "YESMusic"); // set file
}
zipFile.Save(zipPath);
}
Where is the problem ? Need a change in AddFile function ? Thanks
This will work:
using (ZipFile zipFile = new ZipFile())
{
zipFile.Password = "asd";
zipFile.Encryption = EncryptionAlgorithm.PkzipWeak;
// Adding folders in the base directory
foreach (var item in Directory.GetDirectories(filename))
{
string folderName = new DirectoryInfo(item).Name;
zipFile.AddDirectory(item, folderName);
}
// Adding files in the base directory
foreach (string file in Directory.GetFiles(filename))
{
zipFile.AddFile(file);
}
zipFile.Save(zipPath);
}
I can do this so simply with files, like so:
public static void MoveAllFilesFromDesktopToJDrive()
{
DirectoryInfo di = new DirectoryInfo(#"C:\Users\Tafe\Desktop\");
DirectoryInfo Jdrive = new DirectoryInfo(#"J:\");
foreach (FileInfo fi in di.GetFiles())
{
if (Path.GetFileName(fi.FullName) != "desktop.ini")
{
fi.MoveTo(Jdrive.FullName + Path.GetFileName(fi.FullName));
}
}
}
But trying the same operation on directories tells me I can't move directories accross volumes. OK then, so this is what I've tried:
public static void MoveAllDirsFromDeskTopToJDrive()
{
DirectoryInfo di = new DirectoryInfo(#"C:\Users\Tafe\Desktop\");
DirectoryInfo Jdrive = new DirectoryInfo(#"J:\");
foreach (DirectoryInfo dirs in di.GetDirectories())
{
Directory.CreateDirectory(Jdrive + Path.GetFileName(dirs.FullName));
}
}
This copies the names of the files, but not the contents, I would just move the contents like I did with my MoveAllFilesFromDesktopToJDrive() method, but the directories contain subdirectories and subdirectories and such, so I can't figure it out. I know a TINY bit about recursion, but not enough to even attempt this. Also, It can't be that hard can it? There has to be something better in the API to facilitate this? If not, any help to complete this method MoveAllFilesFromDesktopToJDrive() would be a lifesaver!
Try looping this somewhere within your code:
string fileName = "test.txt";
string sourcePath = #"C:\Users\Public\TestFolder";
string targetPath = #"C:\Users\Public\TestFolder\SubDir";
// Use Path class to manipulate file and directory paths.
string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
string destFile = System.IO.Path.Combine(targetPath, fileName);
// To copy a folder's contents to a new location:
// Create a new target folder, if necessary.
if (!System.IO.Directory.Exists(targetPath))
{
System.IO.Directory.CreateDirectory(targetPath);
}
System.IO.File.Copy(sourceFile, destFile, true);
For more details visit this link : http://msdn.microsoft.com/en-us/library/cc148994.aspx
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