Recursively Transfer And Break Up Files/Folders - c#

I wrote an app for going through very large fileshares and while it copies them to the new location, another HD in this case, it breaks what's being copied over into folders containing 4,500 or less items(Libraries to be synced to sharepoint online). Compensating for long file paths. Here is a code sample of the functions I have working in tandem that takes in the source and destination then does the copying breaking described above:
Edit:
Alright I found a solution and this method below is working as I want it to, it is really slow as you can imagine looking at how I have it counting the childitems as it's running though so if anyone has a better/faster solution to the problem please feel free to post it. Otherwise, thank you all very much for the help, it's much appreciated. Here's the code I currently have:
#region Recursive_Copy
public static List<string> OutOfReachAreas = new List<string>();
private static List<FileInfo> Overflow = new List<FileInfo>();
private static List<string> AccessDeniedList = new List<string>();
private static bool FirstTime = true;
private static int LibraryCount { get; set; }
private static bool ToSwith = false;
private static int CountLimit = 4250;
public static void RecursiveCopy(string SourceDir, string DestDir)
{
if (!FirstTime)
{
LibraryCount =
((Directory.GetDirectories((Program.DestinationContainer + "\\" + "Library" + Program.LibraryCounter.ToString()), "*", SearchOption.AllDirectories).Count())
+ (Directory.GetFiles((Program.DestinationContainer + "\\" + "Library" + Program.LibraryCounter.ToString()), "*", SearchOption.AllDirectories).Count()));
}
if (LibraryCount <= CountLimit && !FirstTime)
{
try
{
DirectoryInfo dir = new DirectoryInfo(SourceDir);
DirectoryInfo[] dirs = dir.GetDirectories();
FileInfo[] files = dir.GetFiles();
string CurrentLibrary = "Library" + Program.LibraryCounter.ToString();
if (!Directory.Exists(DestDir))
{
Directory.CreateDirectory(DestDir);
}
if (Overflow.Count() != 0)
{
foreach (var OverflowInst in Overflow)
{
string NewestLibrary = Program.DestinationContainer + "\\" + "Library" + Program.LibraryCounter + "\\" + OverflowInst.Name;
if (!File.Exists(NewestLibrary))
{
OverflowInst.CopyTo(NewestLibrary, false);
}
}
Overflow.Clear();
}
foreach (var file in files)
{
try
{
DirectoryInfo TestPath = new DirectoryInfo(Program.DestinationContainer + "\\" + CurrentLibrary);
int TestPathCount = (TestPath.GetDirectories("*", SearchOption.AllDirectories).Count()) + (TestPath.GetFiles("*", SearchOption.AllDirectories).Count());
if (TestPathCount <= CountLimit)
{
string temppath = Path.Combine(DestDir, file.Name);
DirectoryInfo TestTemp = new DirectoryInfo(temppath);
if (!TestTemp.Exists && !AccessDeniedList.Contains(file.Name))
{
file.CopyTo(temppath, true);
}
}
else
{
FileInfo OverflowToAdd = new FileInfo(file.FullName);
Overflow.Add(OverflowToAdd);
}
}
catch (UnauthorizedAccessException)
{
AccessDeniedList.Add(file.Name);
}
}
foreach (var subDir in dirs)
{
DirectoryInfo TestPath = new DirectoryInfo(Program.DestinationContainer + "\\" + CurrentLibrary);
int TestPathCount = (TestPath.GetDirectories("*", SearchOption.AllDirectories).Count()) + (TestPath.GetFiles("*", SearchOption.AllDirectories).Count());
if (TestPathCount <= CountLimit)
{
if (ToSwith)
{
ToSwith = false;
string PathToSwitch = Program.DestinationContainer + "\\" + "Library" + Program.LibraryCounter.ToString();
RecursiveCopy(SourceDir, PathToSwitch);
}
string temppath = Path.Combine(DestDir, subDir.Name);
RecursiveCopy(subDir.FullName, temppath);
}
else
{
DirectoryInfo CurrentDir = new DirectoryInfo(DestDir);
RecursiveCopy(SourceDir, (Program.DestinationContainer + "\\" + "Library" + Program.LibraryCounter.ToString()));
}
}
}
catch (PathTooLongException)
{
DirectoryInfo DirInst = new DirectoryInfo(SourceDir);
OutOfReachAreas.Add(DirInst.FullName);
}
catch (Exception e)
{
Console.WriteLine("\nError During Copying:\n" + e.Message);
}
}
else
{
++Program.LibraryCounter;
FirstTime = false;
ToSwith = true;
string LibraryToMake = Program.DestinationContainer + "\\" + "Library" + (Program.LibraryCounter.ToString());
Console.WriteLine("Building Library" + (Program.LibraryCounter.ToString()) + "...");
Directory.CreateDirectory(LibraryToMake);
RecursiveCopy(SourceDir, LibraryToMake);
}
}
#endregion

Like chais said in comments, you need the subdirectory search to be recursive.
The MS example calls itself for EACH subdirectory, so it walks the entire directory tree. You could do something similar by replacing:
foreach (var dir in FolderList1)
{
Destination = Destination + "\\" + dir.Name;
CopyItems(dir, Destination);
}
with
foreach (var dir in FolderList1)
{
Destination = Destination + "\\" + dir.Name;
CopyItems(dir, Destination);
foreach (Directory subDir in dir.GetDirectories())
{
BreakMain(subDir, Destination);
}
}
You've got some other things that will have to be fixed to move to this recursive design, but that's the jist of the MS example.

Related

Get files from a folder that I have created in Xamarin.Android

I want get all files from an external storage folder(wall_e_imgs)..Here are codes-
public void getImages()
{
var path1 = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath.ToString();
string path = System.IO.Path.Combine(path1, "wall_e_imgs");
//var files= System.IO.Directory.GetFiles(Android.OS.Environment.ExternalStorageDirectory.ToString() + "wall_e_imgs");
//var files = System.IO.Directory.GetFiles(path);
//string path = Android.OS.Environment.ExternalStorageDirectory.ToString() + "/wall_e_imgs";
//File directory=new File(path);
Java.IO.File directory = new Java.IO.File(path);
Java.IO.File[] files = directory.ListFiles();//always count is 0 even though there are lot files there
foreach (var i in files)
{
FileInfo info = new FileInfo(i.Name);
if (info.Name.Contains("Wall_e"))
{
di.Add(new DownloadedImages { Path1 = info.DirectoryName, Name1 = info.FullName });
}
}
}
But it always give 0 files even though there are lot of files.
Try this
var folder = Android.OS.Environment.ExternalStorageDirectory + Java.IO.File.Separator + "yourfoldername";
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
var filesList = Directory.GetFiles(folder);
foreach (var file in filesList)
{
var filename = Path.GetFileName(file);
}
Try something like this:
// Use whatever folder path you want here, the special folder is just an example
string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "wall_e_imgs");
if (Directory.Exists(folderPath))
{
var files = Directory.EnumerateFiles(folderPath);
foreach (var file in files)
{
// Do your stuff
}
}
Please note that this uses the Directory class from System.IO, not Java.IO
ffilelist will contain a list of mp3 files in "/storage/emulated/0/Music/"
string phyle;
string ffilelist = "";
public void listfiles()
{
try
{
var path1 = "/storage/emulated/0/Music/";
var mp3Files = Directory.EnumerateFiles(path1, "*.mp3", SearchOption.AllDirectories);
foreach (string currentFile in mp3Files)
{
phyle = currentFile;
ffilelist = ffilelist + "\n" + phyle;
}
//playpath(phyle); // play the last file found
}
catch (Exception e9)
{
Toast.MakeText(ApplicationContext, "ut oh\n"+e9.Message , ToastLength.Long).Show();
}
}

C# recursive function

THIS QUESTION IS ANSWERED!
I need to get all files from dropbox. But I cant finish my recursive function, it doesnt work, i have an idea why it doesnt work, but i dont know how to fix it
private void getAllFiles(string path)
{
var dropCon = DatabaseDropbox.Instance();
if (dropCon.IsConnect())
{
ICloudDirectoryEntry folder = dropCon.DropboxStorage.GetFolder(path);
foreach (ICloudFileSystemEntry fsentry in folder)
{
if (fsentry is ICloudDirectoryEntry) // IF FOLDER
{
}
else // IF FILE
{
Console.WriteLine(path + " " + fsentry.Name);
ListViewItem lvi = new ListViewItem(fsentry.Name);
lvi.SubItems.Add(path);
listViewFolders.Items.Add(lvi);
}
}
foreach (ICloudFileSystemEntry fsentry in folder)
{
if (fsentry is ICloudDirectoryEntry) // IF FOLDER
{
var mpath = path + "/" + fsentry.Name;
getAllFiles(mpath);
}
else // IF FILE
{
Console.WriteLine(path + " " + fsentry.Name);
ListViewItem lvi = new ListViewItem(fsentry.Name);
lvi.SubItems.Add(path);
listViewFolders.Items.Add(lvi);
}
}
}
}
If its finds file, it adds it to the list (C# form).
HOW IT DOESNT WORK:
It will list all files in the first directory,
then it will go to the first folder found, lets call that folder "fol1".
After it scans all "fol1", it adds found files to the list, which is good.
But then , when it should go back and search for more files in other directories , "fol2","fol3". Recursion just exists itself and it doesnt do that. So thats my problem.
FOUND RESULTS:
https://gyazo.com/fda8fde13dfbf32f35d39b87712b5751
ACTUAL FOLDERS:
https://gyazo.com/619e5c46bbc113d7d23a56b225f4f209
https://gyazo.com/265034521f317bf0d308910929d1664c
https://gyazo.com/ed9fe5375e1b21f54bbd1f127085c255
Thanks.
WORKING CODE :
private void getAllFiles(string path)
{
var dropCon = DatabaseDropbox.Instance();
if (dropCon.IsConnect())
{
ICloudDirectoryEntry folder = dropCon.DropboxStorage.GetFolder(path);
foreach (ICloudFileSystemEntry fsentry in folder)
{
if (fsentry is ICloudDirectoryEntry) // IF FOLDER
{
var mpath = path + "/" + fsentry.Name;
getAllFiles(mpath);
}
else // IF FILE
{
Console.WriteLine(path + " " + fsentry.Name);
ListViewItem lvi = new ListViewItem(fsentry.Name);
lvi.SubItems.Add(path);
listViewFolders.Items.Add(lvi);
}
}
}
}
private void getAllFiles(string path)
{
var dropCon = DatabaseDropbox.Instance();
if (dropCon.IsConnect())
{
ICloudDirectoryEntry folder = dropCon.DropboxStorage.GetFolder(path);
foreach (ICloudFileSystemEntry fsentry in folder)
{
if (fsentry is ICloudDirectoryEntry) // IF FOLDER
{
var mpath = path + "/" + fsentry.Name;
getAllFiles(mpath);
}
else // IF FILE
{
Console.WriteLine(path + " " + fsentry.Name);
ListViewItem lvi = new ListViewItem(fsentry.Name);
lvi.SubItems.Add(path);
listViewFolders.Items.Add(lvi);
}
}
}
}

Move files to folder but ignore certain ones

I'm trying to move text files into a folder but ignore test.txt and all others will be moved to FileHolder folder. When I run it it still moves all the txt files to the folder.
private void testmodule()
{
string filepath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
DirectoryInfo d = new DirectoryInfo(filepath);
List<String> AllDeskTopFiles = Directory.GetFiles(filepath, "*.txt*").ToList();
foreach (string file in AllDeskTopFiles)
{
if (file != "test.txt")
{
FileInfo mFile = new FileInfo(file);
if (new FileInfo(d + "\\FileHolder\\" + mFile.Name).Exists == false)
mFile.MoveTo(d + "\\FileHolder\\" + mFile.Name);
}
}
}
Your file variable contains the full path.
You need to filter based on the file name, not the full path.
You could just do the filter in the LINQ statement:
var allDeskTopFiles = Directory
.GetFiles(filepath, "*.txt*")
.Where(f => !f.EndsWith("test.txt", StringComparison.InvariantCultureIgnoreCase);
foreach (string file in allDeskTopFiles)
{
// Move all files now
Directory.GetFiles returns the names of files (including their paths) in the specified directory.
So you need to apply a method to extract only the filename
foreach (string file in AllDeskTopFiles)
{
if (Path.GetFileName(file).ToLower() != "test.txt")
{
FileInfo mFile = new FileInfo(file);
if (new FileInfo(d + "\\FileHolder\\" + mFile.Name).Exists == false)
mFile.MoveTo(d + "\\FileHolder\\" + mFile.Name);
}
}
Also creating a FileInfo for every loop just to test the existence or not of the file seems a bit expensive
string destPath = Path.Combine(filepath, "FileHolder");
foreach (string file in AllDeskTopFiles)
{
string fileToMove = Path.GetFileName(file).ToLower();
if (fileToMove != "test.txt")
{
string destFile = Path.Combine(destPath, fileToMove);
if (!File.Exists(destFile))
File.Move(file, destFile);
}
}
You can either check the file name, like this:
DirectoryInfo dirInfo = new DirectoryInfo("old");
foreach (FileInfo fi in dirInfo.GetFiles("*.txt"))
{
if (fi.Name != "test.txt")
File.Copy(fi.FullName, "new/" + fi.Name);
}
Or change your code to check if !file.Contains("text.txt") instead of if file != "test.txt
Following should fix it, A cleaner way now:
private void testmodule()
{
string filepath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
DirectoryInfo d = new DirectoryInfo(filepath);
List<String> AllDeskTopFiles = Directory.GetFiles(filepath, "*.txt*").ToList();
foreach (string file in AllDeskTopFiles)
{
//if (file.ToLower().EndsWith("test.txt"))
//{
// FileInfo mFile = new FileInfo(file);
// if (new FileInfo(d + "\\FileHolder\\" + mFile.Name).Exists == false)
// mFile.MoveTo(d + "\\FileHolder\\" + mFile.Name);
//}
FileInfo mFile = new FileInfo(file);
if(mFile.Name.ToLower() != "test.txt")
{
if (new FileInfo(d + "\\FileHolder\\" + mFile.Name).Exists == false)
mFile.MoveTo(d + "\\FileHolder\\" + mFile.Name);
}
}
}

c# how to get window explorer Directory path under mouse cursor

I want to get window explorer Directory path under mouse cursor.
I tried AutomationElement but it only detect name or process id etc that I dont want. I
also tried SHDocVw.ShellWindows It seems working but I cant define which one is choosen.
here is a source i tried
string GetDropPath(AutomationElement element){
string dir = element.Current.Name;
if (dir.Split('.').Length >= 2) return null;
string desktop = CommonDir["Desktop"];
if (Directory.Exists(desktop + "\\" + dir))
{
dir = desktop + "\\" + dir;
}
else
{
if (CommonDir.ContainsKey(dir))
{
dir = CommonDir[dir];
}
else if (!Directory.Exists(dir))
{
foreach (InternetExplorer item in new SHDocVw.ShellWindows())
{
//uint ppid = 0;
//GetWindowThreadProcessId(item.HWND, out ppid);
if (item.LocationURL.ToString().StartsWith("file:///"))
{
List<int> children = GetAllChildrenWindowHandles(item.HWND, 100);
if (item.HWND == element.Current.NativeWindowHandle || children.Contains(element.Current.NativeWindowHandle))
{
string pth = item.LocationURL.Replace("file:///", "");
if (Directory.Exists(pth + "\\" + dir))
{
dir = pth + "\\" + dir;
}
else
{
dir = pth;
}
break;
}
}
}
}
}
if (Directory.Exists(dir))
{
return dir;
}
else
{
return null;
}
}

listing virtual directories permissions

So I ran across this article for listing out virtual directories. And the article shows how I can specify a username and password for DirectoryEntry. But I'm still getting Access is denied.
There is still something I'm not grasping about permissions. Any ideas?
class Program
{
static void Main(string[] args)
{
//http://www.developmentnow.com/blog/2004/12/29/recursively-list-virtual-directories-in-iis-with-c-and-directoryservices/
// call the function once to kick it off
WriteVDirs("localhost", 2, "");
}
// function that recursively walks through IIS dir & vdirs & lists all the virtual directories
public static void WriteVDirs(string serverName, int SiteNumber, string path)
{
DirectoryEntry de =
new DirectoryEntry("IIS://" + serverName + "/W3SVC/" +
SiteNumber.ToString() + "/Root" + path);
de.Username = "my-machine/administrator";
de.Password = "admin";
DirectoryEntries dirs;
try
{
dirs = de.Children;
foreach (DirectoryEntry d in dirs)
{
if (0 == String.Compare(d.SchemaClassName, "IIsWebDirectory"))
{
string fullPath = path + "/" + d.Name;
WriteVDirs(serverName, SiteNumber, fullPath);
}
else if (0 == String.Compare(d.SchemaClassName, "IIsWebVirtualDir"))
{
string fullPath = path + "/" + d.Name;
Console.WriteLine(fullPath + " : " + d.Properties["Path"].Value);
WriteVDirs(serverName, SiteNumber, fullPath);
}
}
}
catch (Exception ex)
{
Console.WriteLine("ERROR: " + ex.Message);
}
}
}

Categories