Directory.GetFiles how to access subdirectories? [duplicate] - c#

This question already has answers here:
Get all sub directories that only contain files
(4 answers)
Closed 9 years ago.
How can I get files from sub-directories as well, using this code only gets the job done for files under the directory listed:
DirectoryInfo selDir = new DirectoryInfo(folderBrowserDialog1.SelectedPath);
Directory.CreateDirectory(folderBrowserDialog1.SelectedPath + "\\Output");
foreach (FileInfo d in selDir.GetFiles())
{
//my code
}

var allFiles = selDir.GetFiles("*.*", SearchOption.AllDirectories);

I usually make a recurring method to do this. Example:
private void getFiles(string directory)
{
string[] files = Directory.GetFiles(directory);
string[] directories = Directory.GetDirectories(directory);
foreach (string file in files)
{
// Code here.
}
foreach (string subDirectory in directories)
{
// Call the same method on each directory.
getFiles(subDirectory);
}
}

You have the DirectoryInfo of your desired folder, so loop over all it's directories, then you can get the files for each.
DirectoryInfo selDir = new DirectoryInfo(folderBrowserDialog1.SelectedPath);
Directory.CreateDirectory(Path.Combine(folderBrowserDialog1.SelectedPath, "Output"));
foreach (string dir in System.IO.Directory.GetDirectories(selDir.FullName, "*.*", System.IO.SearchOption.AllDirectories))
{
foreach (string file in Directory.GetFiles(dir))
{
//my code
}
}

DirectoryInfo selDir = new DirectoryInfo(folderBrowserDialog1.SelectedPath);
Directory.CreateDirectory(folderBrowserDialog1.SelectedPath + "\\Output");
string[] files = Directory.GetFiles(selDir.FullName, "*.*", SearchOption.AllDirectories);
foreach (string file in files)
{
// your code
}

Related

Copy files and backup the existing + subdirectories

I am trying to make a program to backup files from a particular folder, along with the files within the subfolders of the main folder to another backup folder.
This is part of the code I am trying to accomplish the goal, however I am getting backed up only the files from the main folder, and the subfolders are being copied entirely(all of the files in them).
public static string[] Backup(string sourceDirectory, string targetDirectory, string backupDirectory)
{
DirectoryInfo diBackup = new DirectoryInfo(backupDirectory);
DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);
List<string> dups = new List<string>();
string[] fileNamesSource = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories);
string[] fileNamesDest = Directory.GetFiles(targetDirectory, "*", SearchOption.AllDirectories);
List<string> dupNS = new List<string>();
List<string> dupND = new List<string>();
List<string> BCKP = new List<string>();
string replacement = "";
for (int i = 0; i < fileNamesDest.Length; i++)
{
string res = fileNamesDest[i].Replace(targetDirectory, replacement);
dupND.Add(res);
}
foreach (var ns in fileNamesSource)
{
string res = ns.Replace(sourceDirectory, replacement);
dupNS.Add(res);
}
var duplicates = dupND.Intersect(dupNS);
string[] DuplicatesStringArray = duplicates.ToArray();
foreach (var dup in DuplicatesStringArray)
{
string res = targetDirectory + dup;
BCKP.Add(res);
}
string[] ToBeBackedUp = BCKP.ToArray();
Directory.CreateDirectory(diBackup.FullName);
// Copy each file into the new directory.
foreach (FileInfo fi in diTarget.GetFiles())
{
if (ToBeBackedUp.Contains(fi.FullName)){
fi.CopyTo(Path.Combine(diBackup.FullName, fi.Name), true);
}
}
// Copy each subdirectory using recursion.
foreach (DirectoryInfo diSourceSubDir in diTarget.GetDirectories())
{
if (ToBeBackedUp.Contains(diSourceSubDir.FullName)) {
DirectoryInfo nextTargetSubDir =
diBackup.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir);
}
}
return ToBeBackedUp;
}
Any ideas of how can I copy only the files in the subfolders that exist in the "source" folder?
Also the CopyAll function:
public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
Directory.CreateDirectory(target.FullName);
// Copy each file into the new directory.
foreach (FileInfo fi in source.GetFiles())
{
fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
}
// Copy each subdirectory using recursion.
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
{
DirectoryInfo nextTargetSubDir =
target.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir);
}
}
Thanks in advance.
You can try this way as
Much easier
//Now Create all of the directories
foreach (string dirPath in Directory.GetDirectories(SourcePath, "*",
SearchOption.AllDirectories))
Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));
//Copy all the files & Replaces any files with the same name
foreach (string newPath in Directory.GetFiles(SourcePath, "*.*",
SearchOption.AllDirectories))
File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath), true);
A simple solution: in your CopyAll method, load the SearchOption.AllDirectories argument to your GetFiles method:
foreach (FileInfo fi in source.GetFiles("*", SearchOption.AllDirectories))
{
fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
}
You can use Directory.GetFiles along with SearchOption.AllDirectories to extract the files from the sub-folders as well:
Directory.GetFiles(path, *search pattern goes here*, SearchOption.AllDirectories)

Use a value from a textbox in another class [duplicate]

This question already has answers here:
Copy the entire contents of a directory in C#
(28 answers)
Copy file from one directory to another
(5 answers)
Closed 5 years ago.
Okay, so I have a text box in my program where a user can enter a value, however I am wanting to call this value in another class.
public static void Main()
{
string sourceDirectory = #"F:\RootFolder\testingfolder\Test";
string targetDirectory = #"c:\targetDirectory"; //this is where the value would site
Copy(sourceDirectory, targetDirectory);
}
Not 100% sure on how to call this.
Edit
After some much needed research I have found the below to work for me;
private void CopyInstallFiles(object sender, EventArgs e)
{
string sourceDirectory = #"F:somepath";
string targetDirectory = directoryImput.Text;
//Copy all the files & Replaces any files with the same name
foreach (string newPath in System.IO.Directory.GetFiles(sourceDirectory, "*.*",
SearchOption.AllDirectories))
File.Copy(newPath, newPath.Replace(sourceDirectory, targetDirectory), true);
I just realized that you are looking for a method to move all files and folders - silly me. Here, have some example from https://msdn.microsoft.com/en-us/library/bb762914.aspx :
using System;
using System.IO;
class DirectoryCopyExample
{
static void Main()
{
// Copy from the current directory, include subdirectories.
DirectoryCopy(".", #".\temp", true);
}
private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
{
// Get the subdirectories for the specified directory.
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
if (!dir.Exists)
{
throw new DirectoryNotFoundException(
"Source directory does not exist or could not be found: "
+ sourceDirName);
}
DirectoryInfo[] dirs = dir.GetDirectories();
// If the destination directory doesn't exist, create it.
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
// Get the files in the directory and copy them to the new location.
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
string temppath = Path.Combine(destDirName, file.Name);
file.CopyTo(temppath, false);
}
// If copying subdirectories, copy them and their contents to new location.
if (copySubDirs)
{
foreach (DirectoryInfo subdir in dirs)
{
string temppath = Path.Combine(destDirName, subdir.Name);
DirectoryCopy(subdir.FullName, temppath, copySubDirs);
}
}
}
}
Short version - place it in DirectoryManager.cs and call by DirectoryManager.CopyDirectory(source, destination):
using System.IO;
class DirectoryManager
{
internal static void CopyDirectory(string input, string output)
{
DirectoryInfo dir = new DirectoryInfo(input);
if (dir.Exists)
{
DirectoryInfo[] dirs = dir.GetDirectories();
Directory.CreateDirectory(output);
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
string temppath = Path.Combine(output, file.Name);
file.CopyTo(temppath, false);
}
foreach (DirectoryInfo subdir in dirs)
{
string temppath = Path.Combine(output, subdir.Name);
CopyDirectory(subdir.FullName, temppath);
}
}
}
}

C# Searching for files and folders except in certain folders

Is there any way to exclude certain directories from SearchOption using LINQ command like this
string path = "C:\SomeFolder";
var s1 = Directory.GetFiles(path , "*.*", SearchOption.AllDirectories);
var s2 = Directory.GetDirectories(path , "*.*", SearchOption.AllDirectories);
The path consists of Sub1 and Sub2 Folders with certain files in it. I need to exclude them from directory search.
Thanks
This Worked:
string[] exceptions = new string[] { "c:\\SomeFolder\\sub1",
"c:\\SomeFolder\\sub2" };
var s1 = Directory.GetFiles("c:\\x86", "*.*",
SearchOption.AllDirectories).Where(d => exceptions.All(e =>
!d.StartsWith(e)));
This helped with Exceptions
No there isn't as far as I know. But you could use very simple LINQ to do that in a single line.
var s1 = Directory.GetFiles(path , "*.*", SearchOption.AllDirectories).Where(d => !d.StartsWith("<EXCLUDE_DIR_PATH>")).ToArray();
You can easily combine multiple exclude DIRs too.
You can't do exactly what you want with simple LINQ methods. You will need to write a recursive routine instead of using SearchOption.AllDirectories. The reason is that you want to filter directories not files.
You could use the following static method to achieve what you want:
public static IEnumerable<string> GetFiles(
string rootDirectory,
Func<string, bool> directoryFilter,
string filePattern)
{
foreach (string matchedFile in Directory.GetFiles(rootDirectory, filePattern, SearchOption.TopDirectoryOnly))
{
yield return matchedFile;
}
var matchedDirectories = Directory.GetDirectories(rootDirectory, "*.*", SearchOption.TopDirectoryOnly)
.Where(directoryFilter);
foreach (var dir in matchedDirectories)
{
foreach (var file in GetFiles(dir, directoryFilter, filePattern))
{
yield return file;
}
}
}
You would use it like this:
var files = GetFiles("C:\\SearchDirectory", d => !d.Contains("AvoidMe", StringComparison.OrdinalIgnoreCase), "*.*");
Why the added complexity? This method completely avoids looking inside directories you're not interested in. The SearchOption.AllDirectories will, as the name suggests, search within all directories.
If you're not familiar with iterator methods (the yield return syntax), this can be written differently: just ask!
Alternative
This has almost the same effect. However, it still finds files within subdirectories of the directories you want to ignore. Maybe that's OK for you; the code is easier to follow.
public static IEnumerable<string> GetFilesLinq(
string root,
Func<string, bool> directoryFilter,
string filePattern)
{
var directories = Directory.GetDirectories(root, "*.*", SearchOption.AllDirectories)
.Where(directoryFilter);
List<string> results = new List<string>();
foreach (var d in directories)
{
results.AddRange(Directory.GetFiles(d, filePattern, SearchOption.TopDirectoryOnly));
}
return results;
}
try this
var s2 = Directory.GetDirectories(dirPath, "*", SearchOption.AllDirectories)
.Where(directory => !directory.Contains("DirectoryName"));
///used To Load Files And Folder information Present In Dir In dir
private void button1_Click(object sender, EventArgs e)
{
FileInfo[] fileInfoArr;
StringBuilder sbr=new StringBuilder();
StringBuilder sbrfname = new StringBuilder();
string strpathName = #"C:\Users\prasad\Desktop\Dll";
DirectoryInfo dir = new DirectoryInfo(strpathName);
fileInfoArr = dir.GetFiles("*.dll");
//Load Files From RootFolder
foreach (FileInfo f in fileInfoArr)
{
sbrfname.AppendLine(f.FullName);
}
DirectoryInfo[] dirInfos = dir.GetDirectories("*.*");
//Load Files from folder folder
foreach (DirectoryInfo d in dirInfos)
{
fileInfoArr = d.GetFiles("*.dll");
foreach (FileInfo f in fileInfoArr)
{
sbrfname.AppendLine(f.FullName);
}
sbr.AppendLine(d.ToString());
}
richTextBox1.Text = sbr.ToString();
richTextBox2.Text = sbrfname.ToString();
}

Copying Files Recursively

I found a small snippet for doing a recursive file copy in C#, but am somewhat stumped. I basically need to copy a directory structure to another location, along the lines of this...
Source: C:\data\servers\mc
Target: E:\mc
The code for my copy function as of right now is...
//Now Create all of the directories
foreach (string dirPath in Directory.GetDirectories(baseDir, "*", SearchOption.AllDirectories))
{
Directory.CreateDirectory(dirPath.Replace(baseDir, targetDir));
}
// Copy each file into it’s new directory.
foreach (string file in Directory.GetFiles(baseDir, "*.*", SearchOption.AllDirectories))
{
Console.WriteLine(#"Copying {0}\{1}", targetDir, Path.GetFileName(file));
if (!CopyFile(file, Path.Combine(targetDir, Path.GetFileName(file)), false))
{
int err = Marshal.GetLastWin32Error();
Console.WriteLine("[ERROR] CopyFile Failed on {0} with code {1}", file, err);
}
}
The issue is that in the second scope, I either:
use Path.GetFileName(file) to get the actual file name without the path but I lose the directory "mc" directory structure or
use "file" without Path.Combine.
Either way I have to do some nasty string work. Is there a good way to do this in C# (my lack of knowledge with the .NET API leads me to over complicating things)
MSDN has a complete sample: How to: copy directories
using System;
using System.IO;
class DirectoryCopyExample
{
static void Main()
{
// Copy from the current directory, include subdirectories.
DirectoryCopy(".", #".\temp", true);
}
private static void DirectoryCopy(string sourceDirName, string destDirName,
bool copySubDirs)
{
// Get the subdirectories for the specified directory.
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
if (!dir.Exists)
{
throw new DirectoryNotFoundException(
"Source directory does not exist or could not be found: "
+ sourceDirName);
}
DirectoryInfo[] dirs = dir.GetDirectories();
// If the destination directory doesn't exist, create it.
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
// Get the files in the directory and copy them to the new location.
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
string temppath = Path.Combine(destDirName, file.Name);
file.CopyTo(temppath, false);
}
// If copying subdirectories, copy them and their contents to new location.
if (copySubDirs)
{
foreach (DirectoryInfo subdir in dirs)
{
string temppath = Path.Combine(destDirName, subdir.Name);
DirectoryCopy(subdir.FullName, temppath, copySubDirs);
}
}
}
}
A non-recursive replacement for this answer would be:
private static void DirectoryCopy(string sourceBasePath, string destinationBasePath, bool recursive = true)
{
if (!Directory.Exists(sourceBasePath))
throw new DirectoryNotFoundException($"Directory '{sourceBasePath}' not found");
var directoriesToProcess = new Queue<(string sourcePath, string destinationPath)>();
directoriesToProcess.Enqueue((sourcePath: sourceBasePath, destinationPath: destinationBasePath));
while (directoriesToProcess.Any())
{
(string sourcePath, string destinationPath) = directoriesToProcess.Dequeue();
if (!Directory.Exists(destinationPath))
Directory.CreateDirectory(destinationPath);
var sourceDirectoryInfo = new DirectoryInfo(sourcePath);
foreach (FileInfo sourceFileInfo in sourceDirectoryInfo.EnumerateFiles())
sourceFileInfo.CopyTo(Path.Combine(destinationPath, sourceFileInfo.Name), true);
if (!recursive)
continue;
foreach (DirectoryInfo sourceSubDirectoryInfo in sourceDirectoryInfo.EnumerateDirectories())
directoriesToProcess.Enqueue((
sourcePath: sourceSubDirectoryInfo.FullName,
destinationPath: Path.Combine(destinationPath, sourceSubDirectoryInfo.Name)));
}
}
instead of
foreach (string file in Directory.GetFiles(baseDir, "*.*", SearchOption.AllDirectories))
{
do something like this
foreach (FileInfo fi in source.GetFiles())
{
fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
}

GetFiles with multiple extensions [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can you call Directory.GetFiles() with multiple filters?
How do you filter on more than one extension?
I've tried:
FileInfo[] Files = dinfo.GetFiles("*.jpg;*.tiff;*.bmp");
FileInfo[] Files = dinfo.GetFiles("*.jpg,*.tiff,*.bmp");
Why not create an extension method? That's more readable.
public static IEnumerable<FileInfo> GetFilesByExtensions(this DirectoryInfo dir, params string[] extensions)
{
if (extensions == null)
throw new ArgumentNullException("extensions");
IEnumerable<FileInfo> files = Enumerable.Empty<FileInfo>();
foreach(string ext in extensions)
{
files = files.Concat(dir.GetFiles(ext));
}
return files;
}
EDIT: a more efficient version:
public static IEnumerable<FileInfo> GetFilesByExtensions(this DirectoryInfo dir, params string[] extensions)
{
if (extensions == null)
throw new ArgumentNullException("extensions");
IEnumerable<FileInfo> files = dir.EnumerateFiles();
return files.Where(f => extensions.Contains(f.Extension));
}
Usage:
DirectoryInfo dInfo = new DirectoryInfo(#"c:\MyDir");
dInfo.GetFilesByExtensions(".jpg",".exe",".gif");
You can get every file, then filter the array:
public static IEnumerable<FileInfo> GetFilesByExtensions(this DirectoryInfo dirInfo, params string[] extensions)
{
var allowedExtensions = new HashSet<string>(extensions, StringComparer.OrdinalIgnoreCase);
return dirInfo.EnumerateFiles()
.Where(f => allowedExtensions.Contains(f.Extension));
}
This will be (marginally) faster than every other answer here.
In .Net 3.5, replace EnumerateFiles with GetFiles (which is slower).
And use it like this:
var files = new DirectoryInfo(...).GetFilesByExtensions(".jpg", ".mov", ".gif", ".mp4");
You can't do that, because GetFiles only accepts a single search pattern. Instead, you can call GetFiles with no pattern, and filter the results in code:
string[] extensions = new[] { ".jpg", ".tiff", ".bmp" };
FileInfo[] files =
dinfo.GetFiles()
.Where(f => extensions.Contains(f.Extension.ToLower()))
.ToArray();
If you're working with .NET 4, you can use the EnumerateFiles method to avoid loading all FileInfo objects in memory at once:
string[] extensions = new[] { ".jpg", ".tiff", ".bmp" };
FileInfo[] files =
dinfo.EnumerateFiles()
.Where(f => extensions.Contains(f.Extension.ToLower()))
.ToArray();
You can use LINQ Union method:
dir.GetFiles("*.txt").Union(dir.GetFiles("*.jpg")).ToArray();
The following retrieves the jpg, tiff and bmp files and gives you an IEnumerable<FileInfo> over which you can iterate:
var files = dinfo.GetFiles("*.jpg")
.Concat(dinfo.GetFiles("*.tiff"))
.Concat(dinfo.GetFiles("*.bmp"));
If you really need an array, simply stick .ToArray() at the end of this.
I'm not sure if that is possible. The MSDN GetFiles reference says a search pattern, not a list of search patterns.
I might be inclined to fetch each list separately and "foreach" them into a final list.
I know there is a more elegant way to do this and I'm open to suggestions... this is what I did:
try
{
// Set directory for list to be made of
DirectoryInfo jpegInfo = new DirectoryInfo(destinationFolder);
DirectoryInfo jpgInfo = new DirectoryInfo(destinationFolder);
DirectoryInfo gifInfo = new DirectoryInfo(destinationFolder);
DirectoryInfo tiffInfo = new DirectoryInfo(destinationFolder);
DirectoryInfo bmpInfo = new DirectoryInfo(destinationFolder);
// Set file type
FileInfo[] Jpegs = jpegInfo.GetFiles("*.jpeg");
FileInfo[] Jpgs = jpegInfo.GetFiles("*.jpg");
FileInfo[] Gifs = gifInfo.GetFiles("*.gif");
FileInfo[] Tiffs = gifInfo.GetFiles("*.tiff");
FileInfo[] Bmps = gifInfo.GetFiles("*.bmp");
// listBox1.Items.Add(#""); // Hack for the first list item no preview problem
// Iterate through each file, displaying only the name inside the listbox...
foreach (FileInfo file in Jpegs)
{
listBox1.Items.Add(file.Name);
Photo curPhoto = new Photo();
curPhoto.PhotoLocation = file.FullName;
metaData.AddPhoto(curPhoto);
}
foreach (FileInfo file in Jpgs)
{
listBox1.Items.Add(file.Name);
Photo curPhoto = new Photo();
curPhoto.PhotoLocation = file.FullName;
metaData.AddPhoto(curPhoto);
}
foreach (FileInfo file in Gifs)
{
listBox1.Items.Add(file.Name);
Photo curPhoto = new Photo();
curPhoto.PhotoLocation = file.FullName;
metaData.AddPhoto(curPhoto);
}
foreach (FileInfo file in Tiffs)
{
listBox1.Items.Add(file.Name);
Photo curPhoto = new Photo();
curPhoto.PhotoLocation = file.FullName;
metaData.AddPhoto(curPhoto);
}
foreach (FileInfo file in Bmps)
{
listBox1.Items.Add(file.Name);
Photo curPhoto = new Photo();
curPhoto.PhotoLocation = file.FullName;
metaData.AddPhoto(curPhoto);
}

Categories