What is the best way to move a folder inside itself? - c#

Assuming I want to move a folder inside itself, with its former contents empty but for the new folder, how would I best go about it using code. Normally, in explorer, you would do this by cutting the content of the folder and placing it in a new folder created inside the original folder.
i.e.
Original Path: C:\Users\Previous
New Path: C:\Users\Previous\Previous

cerate the temp folder : c:\user\temp
move the directory with Move from c:\user\previous to : c:\user\temp
rename the temp folder with Move from c:\user\temp to c:\user\previous

As you wanted to move folder and its contents to a sub folder with the same name, you could do as follows:
private void button1_Click(object sender, EventArgs e)
{
CopyContentsToSubFolderWithSameName(#"C:\Users\Previous");
}
private void CopyContentsToSubFolderWithSameName(string path)
{
DirectoryInfo currDir = new DirectoryInfo(path);
DirectoryInfo subDir =
Directory.CreateDirectory(Path.Combine(currDir.FullName, currDir.Name));
IEnumerable<DirectoryInfo> parentFolders =
subDir.Parent.EnumerateDirectories();
// Copy files in the current directory to the destination directory
foreach (FileInfo file in currDir.GetFiles())
{
file.MoveTo(Path.Combine(subDir.FullName, file.Name));
}
// Copy directories (including files) in the current directory
// to the destination directory
foreach (DirectoryInfo dir in parentFolders)
{
if (dir.Name != subDir.Name)
{
dir.MoveTo(Path.Combine(subDir.FullName, dir.Name));
}
}
}

Related

SSIS Script to Delete and Create Folders

I have a loop that runs and creates a bunch of files per folder. The folders are uniquely named based on the order range, so they can change. And the folder must exist or the loop crashes.
I want to create a script that will delete all subfolders and files in each subfolder, from a root dir.
ie
Root = C:\Output\
SubFolder = C:\Output\T1-500\
SubFolder = C:\Output\T501-1010\
SubFolder = C:\Output\T1011-3076\
Then have it create folders as needed on the fly.
I tried:
public void Main()
{
// Deletes subfolders and files in the main folder
EmptyFolder(Dts.Variables["User::FolderName"]);
// Creates new folder on the fly
if (Directory.Exists(Dts.Variables["User::FolderName"].Value = 0))
Dts.TaskResult = Directory.CreateDirectory(Dts.Variables["User::FolderName"]);
}
private void EmptyFolder(DirectoryInfo directoryInfo)
{
foreach (FileInfo file in directoryInfo.GetFiles())
{
file.Delete();
}
foreach (DirectoryInfo subfolder in directoryInfo.GetDirectories())
{
EmptyFolder(subfolder);
}
}
It doesn't seem to pick up my package level variables, and won't let me add new ones.
I get the following when I try to use my folder variable:
The error means you are passing in the wrong data type. Try this.
Instead of this:
EmptyFolder(Dts.Variables["User::FolderName"]);
Use this:
String folderName = (string)Dts.Variables["User::FolderName"].Value;
DirectoryInfo di = new DirectoryInfo(folderName);
EmptyFolder(di);
There is probably a way to put all of it on one line but start with that.
As mentioned in comments below, the (string) cast may not be necessary if you just use the Value property - please also try that.
You will probably also need to use your new folderName string variable in other parts of your code.
As I mentioned in the comments you can also just run a command line like this to remove a folder and all subfolders
RD <yourfolder> /S /Q

How to copy dll file dependency to Temp compilation folder for Azure Function App?

I am working with an azure function app that uses a third-party DLL, that has a dependency on an XML mapping file being present in a folder relative to the current execution. When I publish and run my function on my Azure stack, I run into an exception that the dll cannot load the XML file. I have the XML present in my bin directory with the dll, but Azure appears to be moving the compiled dlls to a temporary folder without the required XML, and proceeds to be looking for the XML relative to that temporary path based on the following exception message:
"Could not find a part of the path 'D:\\local\\Temporary ASP.NET Files\\root\\da2a6178\\25f43073\\assembly\\dl3\\28a13679\\d3614284_4078d301\\Resources\\RepresentationSystem.xml'."
Is there any way I can make sure these additional files are also copied to the temporary folder that Azure is running? Alternatively, can I just force it to run from bin rather than temp?
Update: Unfortunately I am not permitted to share any info on the dll. What I can say is that everything is published to my wwwroot folder, however when outputing some debug info, I can see that the execution is happening from the "Temporary ASP.NET Files" folder. Each dll is copied to its own seperate folder. D:\local\Temporary ASP.NET Files\root\da2a6178\25f43073\assembly\dl3\28a13679\d3614284_4078d301\ThirdParty.dll is that path were the dll in question is, and it lines up with where it expects the xml to be.
While this isn't a true answer to the issue, a workaround for this problem was to have a function in code before the dll functions run, that searches for the dll in question in the Temp ASP.Net folder, and then copies the xml files from a known location to that directory.
// Work Around Begin Here
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
// Check if we are in temp dir
if (assemblyFolder.Contains("Temporary ASP.NET Files"))
{
DirectoryInfo dir = new DirectoryInfo(assemblyFolder);
// Go up 2 dirs
DirectoryInfo top = dir.Parent.Parent;
DirectoryInfo[] dirs = top.GetDirectories();
foreach (DirectoryInfo child in dirs)
{
DirectoryInfo[] dirs2 = child.GetDirectories();
foreach (DirectoryInfo child2 in dirs2)
{
// Find out if this is the Rep
if (File.Exists(child2.FullName + "\\ThirdParty.Representation.dll"))
{
// Look to see if resource folder is there
if (!Directory.Exists(child2.FullName + "\\Resources"))
{
child2.CreateSubdirectory("Resources");
}
DirectoryInfo resDir = new DirectoryInfo(child2.FullName + "\\Resources");
if (File.Exists(resourceDir + "RepresentationSystem.xml"))
{
if(!File.Exists(resDir.FullName + "\\RepresentationSystem.xml"))
{
File.Copy(resourceDir + "RepresentationSystem.xml", resDir.FullName + "\\RepresentationSystem.xml");
}
}
if (File.Exists(resourceDir + "UnitSystem.xml"))
{
if (!File.Exists(resDir.FullName + "\\UnitSystem.xml"))
{
File.Copy(resourceDir + "UnitSystem.xml", resDir.FullName + "\\UnitSystem.xml");
}
}
}
}
}
}
Thank you DoubleHolo for this workaround. It run fine.
I have changed the code adding only Path.Combine to simplify the code.
private void CopyResourcesToTemporaryFolder()
{
// Work Around Begin Here
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string resourceDir = Path.Combine(FileUtils.WebProjectFolder, "Resources");
// Check if we are in temp dir
if (assemblyFolder.Contains("Temporary ASP.NET Files"))
{
DirectoryInfo dir = new DirectoryInfo(assemblyFolder);
// Go up 2 dirs
DirectoryInfo top = dir.Parent.Parent;
DirectoryInfo[] dirs = top.GetDirectories();
foreach (DirectoryInfo child in dirs)
{
DirectoryInfo[] dirs2 = child.GetDirectories();
foreach (DirectoryInfo child2 in dirs2)
{
// Find out if this is the Rep
if (File.Exists(Path.Combine(child2.FullName, "AgGateway.ADAPT.Representation.DLL")))
{
// Look to see if resource folder is there
if (!Directory.Exists(Path.Combine(child2.FullName, "Resources")))
{
child2.CreateSubdirectory("Resources");
}
DirectoryInfo resDir = new DirectoryInfo(Path.Combine(child2.FullName, "Resources"));
if (File.Exists(Path.Combine(resourceDir, "RepresentationSystem.xml")))
{
if (!File.Exists(Path.Combine(resDir.FullName, "RepresentationSystem.xml")))
{
File.Copy(Path.Combine(resourceDir, "RepresentationSystem.xml"), Path.Combine(resDir.FullName, "RepresentationSystem.xml"));
}
}
if (File.Exists(Path.Combine(resourceDir, "UnitSystem.xml")))
{
if (!File.Exists(Path.Combine(resDir.FullName, "UnitSystem.xml")))
{
File.Copy(Path.Combine(resourceDir, "UnitSystem.xml"), Path.Combine(resDir.FullName, "UnitSystem.xml"));
}
}
}
}
}
}
}

C# How to loop through the source folder or subfolders that match the destination

I need to overwrite files from a source to a destination directory.
The structure of each folder is different so i'm trying to do it in a generic way.
The thing is, each folder (source and destination) could have numerous subdirectories or none at all.
The code I currently have is this:
//copy and overwrite the files depending on whatever is in the destination
//search through the destination to find the file
foreach (var dstfile in Directory.GetFiles(targetDir))
{
//search through the source to find the matching file
foreach (var srcfile in Directory.GetFiles(sourceDir))
{
//cut off the source file from the source path
strSrcFile = srcfile.Split(Path.DirectorySeparatorChar).Last();
strDstFile = dstfile.Split(Path.DirectorySeparatorChar).Last();
//if the destination and source files match up, replace the desination with the source
if (strSrcFile == strDstFile)
{
File.Copy(srcfile, Path.Combine(targetDir, Path.GetFileName(strSrcFile)), true);
}
}
}
//look through the subfolders to see if any files match up
foreach (var srcFolder in Directory.GetDirectories(sourceDir))
{
//search through the source for the files
foreach (var srcFile in Directory.GetFiles(srcFolder))
{
//search through the destination for the files
foreach (var dstFile in Directory.GetFiles(targetDir))
{
As you can see there are a lot of foreach loops, is there a way to streamline this?
Make a hash (dictionary) of the destination directory, then walk the source directory and see if the files already exist.
Dictionary<string,string> lut1 = new Dictionary<string,string>();
foreach (var dstfile in Directory.GetFiles(targetDir))
{
strDstFile = dstfile.Split(Path.DirectorySeparatorChar).Last();
lut1 [strDstFile ] = dstfile;
}
foreach (var srcfile in Directory.GetFiles(sourceDir))
{
strSrcFile = srcfile.Split(Path.DirectorySeparatorChar).Last();
string dstfile;
if (lut1.TryGetValue(strSrcFile, out dstfile)) {
File.Copy( srcfile,dstfile,true);
}
}
I haven't tested this but this should work (Not 100% efficient), Should give you some pointers at least
public void UpdateFiles(string directory, string otherDir)
{
var dirFiles = Directory.EnumerateFiles(directory, "*",
SearchOption.AllDirectories);
var otherDirFiles = Directory.EnumerateFiles(otherDir, "*",
SearchOption.AllDirectories);
foreach (var file in dirFiles)
{
string fi = Path.GetFileName(file);
var newFile = otherDirFiles.Where(x => fi == Path.GetFileName(x));
foreach(var foundFile in newFile)
File.Copy(file , foundFile, true);
}
}
I just did it this way in a console app... tested it to work for main target folder and sub folders, although probably not the most efficient.
Call this:
OperateOnSourceFiles(sourceDir, targetDir);
Which will check the current files in the source, and then recursively look through all source subdirectories.
private static void OperateOnSourceFiles(string source, string targetDir)
{
//Processes current source folder files
foreach (var file in Directory.GetFiles(source))
{
OverWrite(targetDir, file);
}
//Recursively processes files in source subfolders
List<string> subfolders = Directory.GetDirectories(source).ToList();
foreach (var subfolder in subfolders)
{
OperateOnSourceFiles(subfolder, targetDir);
}
}
Then your overwrite function could look something like this:
private static void OverWrite(string target, string sourcefile)
{
//Grab file name
var strSrcFile = sourcefile.Split(Path.DirectorySeparatorChar).Last();
//Search current target directory FILES, and copy only if same file name
List<string> targetfiles = Directory.GetFiles(target).Select(file=>file.Split(Path.DirectorySeparatorChar).Last()).ToList();
if (targetfiles.Contains(strSrcFile))
{
File.Copy(sourcefile, Path.Combine(target, Path.GetFileName(strSrcFile)), true);
}
//Recursively search current target directory SUBFOLDERS if any
List<string> subfolders = Directory.GetDirectories(target).ToList();
foreach (var subfolder in subfolders)
{
OverWrite(subfolder, sourcefile);
}
}
Feel free to correct me :)
Note: I realize it's still quite a lot of foreach loops, but at least they aren't nested, and makes life easier when debugging.
I liked the idea, so I tried this myself. Turned out a bit more complicated then I thought it would. Let's go into a deep dive, okay?
The basic idea is to synchronize directories, so we want references to DirectoryInfo instances.
var source = new DirectoryInfo(#"C:\SynchSource");
var target = new DirectoryInfo(#"C:\SynchTarget");
Synchronize(source, target);
Synchronize pretty much works in the following manner:
make sure all files are identical
make sure all directories are identical
go through all subdirectories and traverse
My implementation looks like this:
void Synchronize(DirectoryInfo sourceDir, DirectoryInfo targetDir)
{
SynchronizeFiles(sourceDir, targetDir);
SynchronizeDirectories(sourceDir, targetDir);
TraverseDirectories(sourceDir, targetDir);
}
Note the .Single() - we can never assume there is just one person/process working in the directories.
SynchronizeFiles does two things:
Copy/overwrite all files in the current directory into the target directory.
Remove redundant files that no more exist in the source directory
void MoveFiles(DirectoryInfo sourceDir, DirectoryInfo targetDir)
{
foreach (FileInfo sourceFile in sourceDir.GetFiles())
{
string targetFilePath = Path.Combine(targetDir.FullName, sourceFile.Name);
File.Copy(sourceFile.FullName, targetFilePath);
}
}
void RemoveRedundantFiles(DirectoryInfo sourceDir, DirectoryInfo targetDir)
{
foreach (var targetFile in targetDir.GetFiles())
{
var sourceFilePath = Path.Combine(sourceDir.FullName, targetFile.Name);
if (!File.Exists(sourceFilePath))
{
targetFile.Delete();
}
}
}
We can now assume all files in the current directory are the same, no more and no less. In order to traverse through the subdirectories, we first have to make sure the directory structure is the same. We do it in a similar manner to SynchronizeFiles:
Create missing directories in the target directory (CreateMissingDirectories)
Remove redundant directories that no more exist in the source directory (RemoveRedundantDirectories)
void CreateMissingDirectories(DirectoryInfo sourceDir, DirectoryInfo targetDir)
{
foreach (DirectoryInfo sourceSubDir in sourceDir.GetDirectories())
{
string targetSubDirPath = Path.Combine(targetDir.FullName, sourceSubDir.Name);
if (!Directory.Exists(targetSubDirPath))
{
Directory.CreateDirectory(targetSubDirPath);
}
}
}
void RemoveRedundantDirectories(DirectoryInfo sourceDir, DirectoryInfo targetDir)
{
foreach (DirectoryInfo targetSubDir in targetDir.GetDirectories())
{
string sourceSubDirPath = Path.Combine(sourceDir.FullName, targetSubDir.Name);
if (!Directory.Exists(sourceSubDirPath))
{
targetSubDir.Delete(true);
}
}
}
We are at the state that files and directories in the current level of hierarchy equal. We can now iterate through all subdirectories and call Synchronize:
void TraverseDirectories(DirectoryInfo sourceDir, DirectoryInfo targetDir)
{
foreach (DirectoryInfo sourceSubDir in sourceDir.GetDirectories())
{
DirectoryInfo targetSubDir = targetDir.GetDirectories(sourceSubDir.Name).Single();
Synchronize(sourceSubDir, targetSubDir);
}
}
And we are done.
For huge directory hierarchies, a big amount or large files or even concurrent processes working in the directory, there is much room for improvement. There is a lot of work to do for it to be fast (you may want to cache GetFiles / GetDirectories), skip unnecessary File.Copy calls (get a file hash before assuming a copy is needed).
Just as a side note: Other than synchronizing files every now and then, depending on the requirement, you may want to have a look at FileSystemWatcher, which can detect all changes recursively in a selected directory.

How to get sub-directory names and files from a folder dragged and dropped onto an application

I have the following code, which will process the folder and files in that folder when a user drops it onto a button on my C# Winforms application window. This code works fine:
List<string> filepaths = new List<string>();
foreach (var s in (string[])e.Data.GetData(DataFormats.FileDrop, false))
{
if (Directory.Exists(s))
{
//Add files from folder
filepaths.AddRange(Directory.GetFiles(s));
}
else
{
//Add filepath
filepaths.Add(s);
}
}
However, if there is another folder inside of the main folder (sub-folder), it does not detect that sub-folder and list the files inside of the sub-folder.
Can someone please show me how to detect the name of the sub-folder and the files in the sub-folder as well?
Edit: Would something like this work?
string[] fileList = Directory.GetFiles(#s, "*.*", SearchOption.AllDirectories);
Simalar to Frazell but I like to use file and directory info types like:
Edit: Added a ProcessFile() method
public void ProcessFolder(DirectoryInfo dirInfo)
{
//Check for sub Directories
foreach (DirectoryInfo di in dirInfo.GetDirectories())
{
//Call itself to process any sub directories
ProcessFolder(di);
}
//Process Files in Directory
foreach (FileInfo fi in dirInfo.GetFiles())
{
//Do something with the file here
//or create a method like:
ProcessFile(fi)
}
}
public void ProcessFile(FileInfo fi)
{
//Do something with your file
Debug.Print(fi.FullName);
//...
}
You need to use Directory.GetDirectories() to pull back the subdirectories then loop through them similar to what you're already doing.
// Process all files in the directory passed in, recurse on any directories
// that are found, and process the files they contain.
public static void ProcessDirectory(string targetDirectory)
{
// Process the list of files found in the directory.
string [] fileEntries = Directory.GetFiles(targetDirectory);
foreach(string fileName in fileEntries)
ProcessFile(fileName);
// Recurse into subdirectories of this directory.
string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
foreach(string subdirectory in subdirectoryEntries)
ProcessDirectory(subdirectory);
}
Source: MSDN

How to replicate a folder structure

I want to be able to replicate only the folder structure (not the contents) from one location to another in c# 3.5
for example
C:\Some Folder
+ Folder A
+ Sub Folder A
+ Sub Folder B
+ Sub Folder B1
+ Sub Folder B2
+ Sub Folder C
To New Location
C:\Some New folder
+ Folder A
+ Sub Folder Aetc... etc..
Do you mean you want to create the same files, but not the contents within the same structure.
Something like this might work:
public static TotallyNotRecursiveAndCreateDirs(string root, string newRoot)
{
DirectoryInfo rootDir = new DirectoryInfo(Path.GetPathRoot(root));
DirectoryInfo[] dirs = rootDir.GetDirectories("*", SearchOption.AllDirectories);
foreach(DirectoryInfo dir in dirs)
{
Directory.CreateDirectory(dir.FullName.Replace(root, newRoot));
FileInfo[] files = dir.GetFiles("*.*", SearchOption.TopDirectoryOnly);
foreach(FileInfo file in files)
{
File.Create(file.FullName.Replace(root, newRoot));
}
}
}
You might also want to do some exception checking to ensure that the root and the newRoot parameters are valid (ie: rooted, etc...)
If you don't want the files and just the directories, then just remove the second loop.
To copy a folder structure at src to dest:
Create dest.
(Optional) Set permissions on dest to match src.
For each folder name in src, copy the folder structure at src\name to dest\name.

Categories