How to get files from exact subdirectories - c#

I've managed to get files out of "root" folder subdirectories, but I also get files from these subdirectories directories2, which I don't want to.
Example: RootDirectory>Subdirectories (wanted files)>directories2 (unwanted files)
I've used this code:
public void ReadDirectoryContent()
{
var s1 = Directory.GetFiles(RootDirectory, "*", SearchOption.AllDirectories);
{
for (int i = 0; i <= s1.Length - 1; i++)
FileInfo f = new FileInfo(s1[i]);
. . . etc
}
}

Try this :
var filesInDirectSubDirs = Directory.GetDirectories(RootDirectory)
.SelectMany(d=>Directory.GetFiles(d));
foreach(var file in filesInDirectSubDirs)
{
// Do something with the file
var fi = new FileInfo(file);
ProcessFile(fi);
}
The idea is to first select 1st level of subdirectories, then "aggregate" all files using Enumerable.SelectMany method

You have to change SearchOption.AllDirectories to SearchOption.TopDirectoryOnly, because the first one means that it gets the files from the current directory and all the subdirectories.
EDIT:
The op wants to search in direct child subdirectories, not the root
directory.
public void ReadDirectoryContent()
{
var subdirectories = Directory.GetDirectories(RootDirectory);
List<string> files = new List<string>();
for(int i = 0; i < subdirectories.Length; i++)
files.Concat(Directory.GetFiles(subdirectories[i], "*", SearchOption.TopDirectoryOnly));
}

Related

C# returning all files located in a directory which has folders in it [duplicate]

This question already has answers here:
How to recursively list all the files in a directory in C#?
(23 answers)
Closed 2 years ago.
How can I retrieve all the files in a directory that has files, sub-folders, and files in that folders.
NOTE: The folder/files is not constant
You can use the DirectoryInfo.GetFiles method with the RecurseSubdirectories option.
using System.IO;
FileInfo[] files
= new DirectoryInfo(#"C:\Program Files")
.GetFiles("*", new EnumerationOptions { RecurseSubdirectories = true });
If you don't need the full list of files, it may be faster to enumerate the directory's contents.
using System.IO;
using System.Collections.Generic;
using System.Linq;
var directory = new DirectoryInfo(#"C:\Program Files");
IEnumerable<FileInfo> files
= from file in directory.EnumerateFiles("*", new EnumerationOptions { RecurseSubdirectories = true })
where file.Name = "target.txt"
select file;
foreach (FileInfo file in files)
{
//...
}
You can use Directory.GetFiles(path) and Directory.GetDirectories(path)
static void ScanDir(string path, int spaces = 0)
{
var files = Directory.GetFiles(path);
foreach (var file in files)
{
for (int i = 0; i < spaces; i++)
Console.Write(" "); // Just for styling
Console.WriteLine(file);
}
var dirs = Directory.GetDirectories(path);
foreach (var dir in dirs)
{
ScanDir(dir, spaces + 4);
}
}
static void Main()
{
ScanDir("C:\\path\\to");
}

C# Directory-Searchpattern Subdirectorie(s)

How can I search a Path like that in C#:
"C:\MyApp\*\log"
I want to get all Directories that matches that search pattern.
Example result:
C:\MyApp\20171009\log
C:\MyApp\20171008\log
C:\MyApp\20171007\log
In Powershell it works with get-item
Try this iterator-based file functions:
var path = #"C:\temp";
foreach (var file in Directory.EnumerateFiles(path, "*.log", SearchOption.AllDirectories))
{
Console.WriteLine(file);
}
For more informations show here
If you are trying to just get the directories with Name Log which match the pattern C:\MyApp*\log, following code should help:
var dirs = Directory.EnumerateDirectories(#"C:\Temp\","log", SearchOption.AllDirectories);
Notice that search pattern is the name of directory and not any file name or file extension
I found a solution for my Problem.
I modified it for Directory-Use.
public static List<string> GetAllMatchingPaths(string pattern)
{
char separator = Path.DirectorySeparatorChar;
string[] parts = pattern.Split(separator);
if (parts[0].Contains('*') || parts[0].Contains('?'))
throw new ArgumentException("path root must not have a wildcard", nameof(parts));
return GetAllMatchingPathsInternal(String.Join(separator.ToString(), parts.Skip(1)), parts[0]);
}
private static List<string> GetAllMatchingPathsInternal(string pattern, string root)
{
char separator = Path.DirectorySeparatorChar;
string[] parts = pattern.Split(separator);
for (int i = 0; i < parts.Length; i++)
{
// if this part of the path is a wildcard that needs expanding
if (parts[i].Contains('*') || parts[i].Contains('?'))
{
// create an absolute path up to the current wildcard and check if it exists
var combined = root + separator + String.Join(separator.ToString(), parts.Take(i));
if (!Directory.Exists(combined))
return new List<string>();
if (i == parts.Length - 1) // if this is the end of the path (a file name)
{
return ( List<string> ) Directory.EnumerateFiles(combined, parts[i], SearchOption.TopDirectoryOnly);
}
else // if this is in the middle of the path (a directory name)
{
var directories = Directory.EnumerateDirectories(combined, parts[i], SearchOption.TopDirectoryOnly);
List<string> pts = new List<string>();
foreach ( string directory in directories )
{
foreach ( string item in GetAllMatchingPathsInternal(String.Join(separator.ToString(), parts.Skip(i + 1)), directory))
{
pts.Add(item);
}
}
return pts;
}
}
}

Move files directories and sub directories to another directory Conditionally (Move only Last 5 days created files and directories) in C#

My Source directory "D:\Source"
Destination "D:\Destination"
source directory contains some files and folders with different creation dates,
i want to move all files and folders whose creation date less than last 5 days
for example today is 28/11/2015 and i want to Move all files and folders from source before creating 23/11/205.
i'm searching since 2 days but no success.
here is my Attempt
var sourcePath = "D:\\Source";
var destinationPath = "D:\\Destination";
var dInfo = new DirectoryInfo(sourcePath)
var files = (from filew in dInfo.EnumerateFiles(sourcePath)
orderby filew.CreationTime.Date < DateTime.Now.Date.AddDays(-5) ascending
select filew.Name).Distinct();
var directories = (from filew in dInfo.EnumerateDirectories(sourcePath)
orderby filew.CreationTime.Date < DateTime.Now.Date.AddDays(-5) ascending
select filew.Name).Distinct();
foreach (var dir in directories)
{
var dest = Path.Combine(destinationPath, Path.GetFileName(dir));
Directory.Move(dir, dest);
}
foreach (var file in files)
{
var dest = Path.Combine(destinationPath, Path.GetFileName(file));
File.Move(file, dest);
}
ERROR : Second path fragment must not be a drive or UNC name.
please help me
You have to call EnumerateFiles and EnumerateDirectories without parameters:
dInfo.EnumerateFiles()
dInfo.EnumerateDirectories()
The information about sourcePath is already in the dInfo object. The parameter would be used to apply a filter.
UPDATE:
And the EnumerateFiles() function just returns the file names without pathes. So you should use something like that:
foreach (var file in files)
{
var src = Path.Combine(sourcePath, file);
var dest = Path.Combine(destinationPath, file);
File.Move(src, dest);
}
You would need to do it recursively as there can be sub directories within the directory, where the same rule would apply. Refer to code below.
public static void MoveFilesAndFolders(string sourcePath, string destinationPath)
{
var directories = Directory.GetDirectories(sourcePath);
foreach (var directory in directories)
{
var subDirectory = new DirectoryInfo(directory);
//Create sub directory in the destination folder if the business rules is satisfied
if (DateTime.Today.Subtract(File.GetCreationTime(directory)).Days < 5)
{
var newDestinationDirectory = Directory.CreateDirectory(Path.Combine(destinationPath, subDirectory.Name));
MoveFilesAndFolders(subDirectory.FullName, newDestinationDirectory.FullName);
}
}
foreach (var file in Directory.GetFiles(sourcePath))
{
var fileName = Path.GetFileName(file);
//Copy the file to destination folder if the business rule is satisfied
if (!string.IsNullOrEmpty(fileName))
{
var newFilePath = Path.Combine(destinationPath, fileName);
if (!File.Exists(newFilePath) && (DateTime.Today.Subtract(File.GetCreationTime(file)).Days < 5)))
{
File.Move(file, newFilePath);
}
}
}
}

Find all files in first sub directories

I have an application which searches in all directories behind Documents/GameLauncher/ Like this:
var foundApplications = Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "/GameLauncher", "*.*", SearchOption.AllDirectories).Where(s => s.EndsWith(".exe") || s.EndsWith(".lnk") || s.EndsWith(".url"));
This works fine but now I only want to find all the applications in the first sub directories of this folder. Like this:
GameLauncher/test/test.exe <--- find this file
GameLauncher/test/test/test.exe <--- Ignore this file
GameLauncher/hello/hello.exe <--- find this file
I have searched around and came up with this:
//Search for first sub directories of path
var folders = Directory.GetDirectories(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "/GameLauncher");
IEnumerable<string> foundApplications;
//Use folders to find applications and add them to foundApplications
for (int i = 0; i < folders.Count(); i++)
{
foundApplications += Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "/GameLauncher/" + folders[i], "*.*", SearchOption.AllDirectories).Where(s => s.EndsWith(".exe") || s.EndsWith(".lnk") || s.EndsWith(".url"));
}
//Ends up with error "Use of unassigned local variable 'foundApplications'" when using = instead of += in the forloop above.
foreach (var application in foundApplications){
MessageBox.Show(application.ToString());
}
Does anyone have any tips to solve this problem or even a better way to find those files in the first sub directories of my GameLauncher folder?
Thanks for reading/helping.
Just don't use the "all" option if you don't want all, simple as that.
var path = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
#"GameLauncher");
var includedExtensions = new HashSet<string> { ".exe", ".lnk", ".url" };
var files =
from dir in Directory.EnumerateDirectories(path)
from file in Directory.EnumerateFiles(dir)
let extension = Path.GetExtension(file)
where includedExtensions.Contains(extension)
select file;
You should be working with a list instead of an IEnumerable since it will grow dynamically.
var foundApplications = new List<string>();
var folders = Directory.GetDirectories(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "/GameLauncher");
//Use folders to find applications and add them to foundApplications
for (int i = 0; i < folders.Count(); i++)
{
foundApplications.AddRange(Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "/GameLauncher/" + folders[i], "*.*", SearchOption.AllDirectories).Where(s => s.EndsWith(".exe") || s.EndsWith(".lnk") || s.EndsWith(".url").ToList());
}
foreach (var application in foundApplications){
MessageBox.Show(application.ToString());
}
If you want to append one IEnumerable to another you need to use Concat. You'll also have to initialize foundApplications to an empty IEnumerable.
var folderPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"GameLauncher");
var folders = Directory.GetDirectories(folderPath);
IEnumerable<string> foundApplications = Enumerable<string>.Empty;
//Use folders to find applications and add them to foundApplications
foreach(var subFolder in folders)
{
string path = Path.Combine(folderPath, subFolder);
foundApplications.Concat(
Directory.GetFiles(path, "*.*", SearchOption.TopDirectoryOnly)
.Where(s => s.EndsWith(".exe") || s.EndsWith(".lnk") || s.EndsWith(".url")));
}
foreach (var application in foundApplications){
MessageBox.Show(application.ToString());
}
Also I'm pretty sure you want to use SearchOption.TopDirectoryOnly not SearchOption.AllDirectories

How can recursively search directories with multiple wildcards?

Using C# (.NET), how can I search a file system given a directory search mask like this: (?)
\\server\Scanner\images\*Images\*\*_*
For example, I need to first find all top-level directories:
\\server\Scanner\images\Job1Images
\\server\Scanner\images\Job2Images
...then I need to procede further with the search mask:
\\server\Scanner\images\Job1Images\*\*_*
\\server\Scanner\images\Job2Images\*\*_*
This doesn't seem too complicated but I can't figure it out for the life of me...
As mentioned above, I'm using C# and .NET. The search can be trying to locate directories or files. (i.e. *.txt, or <*Directory>)
Like this:
Top Level Directories:
//get Top level
string[] TopLevel = Directory.GetDirectories(path);
And then you will have to do a resursive function of this folders using wildcard pattern,
for example:
// Only get subdirectories that begin with the letter "p."
string pattern = "p*";
string[] dirs = folder.GetDirectories(path, pattern);
I suggest you play with wildcards to get the array output and you will figure out
which is the best way, if using resursive function or directly quering paths.
Edit: Ahh, new functionality with .NET 4 so you don't have to do a recursive function (Thanks Matthew Brubaker)
IEnumerable<String> matchingFilePaths2 = System.IO.Directory.EnumerateFiles(#"C:\some folder to start in", filePatternToMatchOn, System.IO.SearchOption.AllDirectories);
First Answer:
//get all files that have an underscore - searches all folders under the start folder
List<String> matchingFilePaths = new List<string>();
String filePatternToMatchOn = "*_*";
FileUtilities.GetAllFilesMatchingPattern(#"C:\some folder to start in", ref matchingFilePaths, filePatternToMatchOn);
...
public static void GetAllFilesMatchingPattern(String pathToGetFilesIn, ref List<String> fullFilePaths, String searchPattern)
{
//get all files in current directory that match the pattern
String[] filePathsInCurrentDir = Directory.GetFiles(pathToGetFilesIn, searchPattern);
foreach (String fullPath in filePathsInCurrentDir)
{
fullFilePaths.Add(fullPath);
}
//call this method recursively for all directories
String[] directories = Directory.GetDirectories(pathToGetFilesIn);
foreach (String path in directories)
{
GetAllFilesMatchingPattern(path, ref fullFilePaths, searchPattern);
}
}
public static IEnumerable<string> GetImages()
{
//For each "*Image" directory
foreach (var jobFolder in Directory.EnumerateDirectories(#"\\server\Scanner\images", "*Images"))
{
//For each first level subdirectory
foreach (var jobSubFolder in Directory.EnumerateDirectories(jobFolder))
{
//Enumerate each file containing a '_'
foreach (var filePath in Directory.EnumerateFiles(jobSubFolder, "*_*", SearchOption.TopDirectoryOnly))
{
yield return filePath;
}
}
}
}
Only the files from the first level subdirectories of each "*Image" directory are enumerated.
Finally you can use it with:
foreach (var path in GetImages())
{
Console.WriteLine(path);
}
There is a C# procedure where you can search folder by path pattern with wildcards like * and ?.
Example if path pattern C:\Folder?*\Folder2 is passed to the procedru, then a list of folder path will be returned
C:\Folder1\A\Folder2
C:\FolderA\B\Folder2
...
and so on
static List<string> GetFoldersByPathPattern(string folderPathPattern)
{
List<string> directories = new List<string>();
directories.Add("");
string[] folderParts = folderPathPattern.Split(new char[] { '\\' }, StringSplitOptions.None);
foreach (string folderPart in folderParts)
{
if (folderPart.Contains('*') || folderPart.Contains('?'))
{
List<string> newDirectories = new List<string>();
foreach (string directory in directories)
{
foreach (string newDirectory in Directory.GetDirectories(directory, folderPart))
{
newDirectories.Add(newDirectory);
}
}
directories = newDirectories;
}
else
{
for (int i = 0; i < directories.Count(); i++)
{
directories[i] = directories[i] + folderPart + "\\";
}
}
}
return directories;
}

Categories

Resources