I want to loop through all sub folders and files in a folder and check whether a particular filename contains a folder say "X" in its path (ancestor). I dont want to use string comparison.Is there a better way?
Answering your specific question (the one that is in the title of your question, not in the body), once you have the filename (which other answers tell you how to find), you can do:
bool PathHasFolder(string pathToFileName, string folderToCheck)
{
return Path.GetDirectoryName(pathToFileName)
.Split(Path.DirectorySeparatorChar)
.Any(x => x == folderToCheck);
}
This will work only with absolute paths... if you have relative paths you can complicate it further (this requires the file to actually exist though):
bool PathHasFolder(string pathToFileName, string folderToCheck)
{
return new FileInfo(pathToFileName)
.Directory
.FullName
.Split(Path.DirectorySeparatorChar)
.Any(x => x == folderToCheck);
}
You can use Directory.GetFiles()
// Only get files that begin with the letter "c."
string[] dirs = Directory.GetFiles(#"c:\", "c*");
Console.WriteLine("The number of files starting with c is {0}.", dirs.Length);
foreach (string dir in dirs)
{
Console.WriteLine(dir);
}
https://msdn.microsoft.com/en-us/library/6ff71z1w(v=vs.110).aspx
You can use recursive search like
// sourcedir = path where you start searching
public void DirSearch(string sourcedir)
{
try
{
foreach (string dir in Directory.GetDirectories(sourcedir))
{
DirSearch(dir);
}
// If you're looking for folders and not files take Directory.GetDirectories(string, string)
foreach (string filepath in Directory.GetFiles(sourcedir, "whatever-file*wildcard-allowed*"))
{
// list or sth to hold all pathes where a file/folder was found
_internalPath.Add(filepath);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
So in your case you're looking for folder XYZ, use
// Takes all folders in sourcedir e.g. C:/ that starts with XYZ
foreach (string filepath in Directory.GetDirectories(sourcedir, "XYZ*")){...}
So if you would give sourcedir C:/ it would search in all folders available on C:/ which would take quite a while of course
Related
So I checked out the basic things but I'd like to do the following:
I have 5 files let's say: X1_word_date.pdf, XX1_word_date.pdf, etc...
I'd like to create a folder structure like: C:\PATH\X1, C:\PATH\XX1, etc...
So how do I take the first letters before the '_' in the file names and put it into a string?
My idea is that I use the Directory.CreateDirectory and than combine the main path and the strings so I get the folders.
How do I do that? Help appreciated.
string fileName = "X1_word_date.pdf";
string[] tokens = fileName.Split('_');
string myPath = "C:\\PATH\\";
Directory.CreateDirectory( myPath + tokens[0]);
Something like this should work. Using Split() will also allow for numbers greater than 9 to be dealt with
Supposed that your files is a List<string> which contains the file name (X2_word_date.pdf,...)
files.ForEach(f => {
var pathName= f.Split('_').FirstOrDefault();
if(!string.IsNullOrEmpty(pathName))
{
var directoryInfo = DirectoryInfo(Path.Combine(#"C:\PATH", pathName));
if(!directoryInfo.Exists)
directoryInfo.Create();
//Then move this current file to the directory created, by FileInfo and Move method
}
})
With simple string methods like Split and the System.IO.Path class:
var filesAndFolders = files
.Select(fn => new
{
File = fn,
Dir = Path.Combine(#"C:\PATH", Path.GetFileNameWithoutExtension(fn).Split('_')[0].Trim())
});
If you want to create that folder and add the file:
foreach (var x in filesAndFolders)
{
Directory.CreateDirectory(x.Dir); // will only create it if it doesn't exist yet
string newFileName = Path.Combine(x.Dir, x.File);
// we don't know the old path of the file so i can't show how to move
}
Or using regex
string mainPath = #"C:\PATH";
string[] filenames = new string[] { "X1_word_date.pdf", "X2_word_date.pdf" };
foreach (string filename in filenames)
{
Match foldernameMatch = Regex.Match(filename, "^[^_]+");
if (foldernameMatch.Success)
Directory.CreateDirectory(Path.Combine(mainPath, foldernameMatch.Value));
}
Using the bigger picture starting with only your Source and Destination directory.
We can list all files we need to move with Directory.GetFiles.
In this list We first isolate the filename with GetFileName.
Using simple String.Split you have the new directory name.
Directory.CreateDirectory will create directories unless they already exist.
To move the file we need its destination path, a combinaison of the Destination directory path and the fileName.
string sourceDirectory = #"";
string destDirectory = #"";
string[] filesToMove = Directory.GetFiles(sourceDirectory);
foreach (var filePath in filesToMove) {
var fileName = Path.GetFileName(filePath);
var dirPath = Path.Combine(destDirectory, fileName.Split('_')[0]);
var fileNewPath= Path.Combine(dirPath,fileName);
Directory.CreateDirectory(dirPath);// If it exist it does nothing.
File.Move(filePath, fileNewPath);
}
string[] dirs = System.IO.Directory.GetDirectories(#"C:\Somefolder\");
foreach (string dir in dirs)
{
listBox1.Items.Add(Path.GetFileName(dir));
}
This is my code, and I have no idea how to get ONLY directories which contains name of something in my textbox for example. I have seen that someone had textbox, next to it button update, I tried to do it the same way - you write into textbox name of a folder ex. Windows and it shows ONLY the one folder so if I write Sys it will find System32 and SYSWOW64 && it wont be case sensitive cause I can do simple if condition, but cant make it not case sensitive you know what I mean? my english is pretty bad, had to tell it this way hope its understandable
Probably, you want this
string[] dirs = System.IO.Directory.GetDirectories(#"C:\Somefolder\");
foreach (string dir in dirs.Where(x => x.Contains(textBox1.Text)))
{
listBox1.Items.Add(Path.GetFileName(dir));
}
EDIT
string[] dirs = System.IO.Directory.GetDirectories(#"C:\Somefolder\");
foreach (string dir in dirs.Where(x => x.ToLower().Contains(textBox1.Text.Trim().ToLower())))
{
listBox1.Items.Add(Path.GetFileName(dir));
}
I'd like to browse a directory and get all files with their sizes , names and urls.
I did like this :
int i = 0;
foreach (string sFileName in Directory.GetFiles(Path.Combine(#"C:\Projets", path2)))
{
i++;
}
i count the number of files in a directory but the problem when i have other directories inside it , how can i do to get all files and it caracteristics?
This is a duplicate of many other similar questions. If you want to get extended file info, use the XxxInfo classes, eg DirectoryInfo, FileInfo instead of the Directory and File classes.
Additionally, all GetXXX or EnumerateXXX methods have overloads with the SearchOption parameter which allows you to return all files,not just the files of the top directory.
For your specific question, to get info on all files below a directory using e.g. GetFiles:
var di=new DirectoryInfo(somePath);
var allFiles=di.GetFiles("*",SearchOption.AllDirectories);
foreach(var file in allFiles)
{
Console.WriteLine("{0} {1}",file.Name,file.Length);
}
The difference between GetFiles and EnumerateFiles is that GetFiles returns only after it retrieves all files below a directory, which can take a long time. EnumerateFiles returns an iterator so you can use it in a foreach statement to process each file at a time and stop the iteration if you like by breaking out of the loop.
This should loop through all of the files recursively
foreach (string sFileName in Directory.EnumerateFiles(Path.Combine(#"C:\Projets", path2), "*.*", SearchOption.AllDirectories))
{
//Get file information here
FileInfo f = new FileInfo(sFileName);
Console.WriteLine("{0} - {1}", f.Length, f.Name);
}
I have to create an app that drills into a specific drive, reads all file names and replaces illegal SharePoint characters with underscores.
The illegal characters I am referring to are: ~ # % & * {} / \ | : <> ? - ""
Can someone provide either a link to code or code itself on how to do this? I am VERY new to C# and need all the help i can possibly get. I have researched code on recursively drilling through a drive but i am not sure how to put the character replace and the recursive looping together. Please help!
The advice for removing illegal characters is here:
How to remove illegal characters from path and filenames?
You just have to change the character set to your set of characters that you want to remove.
If you have figured out how to recurse the folders, you can get all of the files in each folder with:
var files = System.IO.Directory.EnumerateFiles(currentPath);
and then
foreach (string file in files)
{
System.IO.File.Move(file, ConvertFileName(file));
}
The ConvertFileName method you will write to accept a filename as a string, and return a filename stripped of the bad characters.
Note that, if you are using .NET 3.5, GetFiles() works too. According to MSDN:
The EnumerateFiles and GetFiles
methods differ as follows: When you
use EnumerateFiles, you can start
enumerating the collection of names
before the whole collection is
returned; when you use GetFiles, you
must wait for the whole array of names
to be returned before you can access
the array. Therefore, when you are
working with many files and
directories, EnumerateFiles can be
more efficient.
How to recursively list directories
string path = #"c:\dev";
string searchPattern = "*.*";
string[] dirNameArray = Directory.GetDirectories(path, searchPattern, SearchOption.AllDirectories);
// Or, for better performance:
// (but breaks if you don't have access to a sub directory; see 2nd link below)
IEnumerable<string> dirNameEnumeration = Directory.EnumerateDirectories(path, searchPattern, SearchOption.AllDirectories);
How to: Enumerate Directories and Files
How to recursively list all the files in a directory in C#?
Not really an answer, but consider both of the following:
The following characters are not valid in filenames anyways so you don't have to worry about them: /\:*?"<>|.
Make sure your algorithm handles duplicate names appropriately. For example, My~Project.doc and My#Project.doc would both be renamed to My_Project.doc.
A recursive method to rename files in folders is what you want. Just pass it the root folder and it will call itself for all subfolders found.
private void SharePointSanitize(string _folder)
{
// Process files in the directory
string [] files = Directory.GetFiles(_folder);
foreach(string fileName in files)
{
File.Move(fileName, SharePointRename(fileName));
}
string[] folders = Directory.GetDirectories(_folder);
foreach(string folderName in folders)
{
SharePointSanitize(folderName);
}
}
private string SharePointRename(string _name)
{
string newName = _name;
newName = newName.Replace('~', '');
newName = newName.Replace('#', '');
newName = newName.Replace('%', '');
newName = newName.Replace('&', '');
newName = newName.Replace('*', '');
newName = newName.Replace('{', '');
newName = newName.Replace('}', '');
// .. and so on
return newName;
}
Notes:
You can replace the '' in the SharePointRename() method to whatever character you want to replace with, such as an underscore.
This does not check if two files have similar names like thing~ and thing%
class Program
{
private static Regex _pattern = new Regex("[~#%&*{}/\\|:<>?\"-]+");
static void Main(string[] args)
{
DirectoryInfo di = new DirectoryInfo("C:\\");
RecursivelyRenameFilesIn(di);
}
public static void RecursivelyRenameFilesIn(DirectoryInfo root)
{
foreach (FileInfo fi in root.GetFiles())
if (_pattern.IsMatch(fi.Name))
fi.MoveTo(string.Format("{0}\\{1}", fi.Directory.FullName, Regex.Replace(fi.Name, _pattern.ToString(), "_")));
foreach (DirectoryInfo di in root.GetDirectories())
RecursivelyRenameFilesIn(di);
}
}
Though this will not handle duplicates names as Steven pointed out.
I have a directory that contains jpg,tif,pdf,doc and xls. The client DB conly contains the file names without extension. My app has to pick up the file and upload the file. One of the properties of the upload object is the file extension.
Is there a way of getting file extension if all i have is the path and name
eg:
C:\temp\somepicture.jpg is the file and the information i have through db is
c:\temp\somepicture
Use Directory.GetFiles(fileName + ".*"). If it returns just one file, then you find the file you need. If it returns more than one, you have to choose which to upload.
Something like this maybe:
DirectoryInfo D = new DirectoryInfo(path);
foreach (FileInfo fi in D.GetFiles())
{
if (Path.GetFileNameWithoutExtension(fi.FullName) == whatever)
// do something
}
You could obtain a list of all of the files with that name, regardless of extension:
public string[] GetFileExtensions(string path)
{
System.IO.DirectoryInfo directory =
new System.IO.DirectoryInfo(System.IO.Path.GetDirectoryName(path));
return directory.GetFiles(
System.IO.Path.GetFileNameWithoutExtension(path) + ".*")
.Select(f => f.Extension).ToArray();
}
Obviously, if you have no other information and there are 2 files with the same name and different extensions, you can't do anything (e.g. there is somepicture.jpg and somepicture.png at the same time).
On the other hand, usually that won't be the case so you can simply use a search pattern (e.g. somepicture.*) to find the one and only (if you're lucky) file.
Search for files named somepicture.* in that folder, and upload any that matches ?
Get the lowest level folder for each path. For your example, you would have:
'c:\temp\'
Then find any files that start with your filename in that folder, in this case:
'somepicture'
Finally, grab the extension off the matching filename. If you have duplicates, you would have to handle that in a unique way.
You would have to use System.IO.Directory.GetFiles() and iterate through all the filenames. You will run into issues when you have a collision like somefile.jpg and somefile.tif.
Sounds like you have bigger issues than just this and you may want to make an argument to store the file extension in your database as well to remove the ambiguity.
you could do something like this perhaps....
DirectoryInfo di = new DirectoryInfo("c:/temp/");
FileInfo[] rgFiles = di.GetFiles("somepicture.*");
foreach (FileInfo fi in rgFiles)
{
if(fi.Name.Contains("."))
{
string name = fi.Name.Split('.')[0].ToString();
string ext = fi.Name.Split('.')[1].ToString();
System.Console.WriteLine("Extension is: " + ext);
}
}
One more, with the assumption of no files with same name but different extension.
string[] files = Directory.GetFiles(#"c:\temp", #"testasdadsadsas.*");
if (files.Length >= 1)
{
string fullFilenameAndPath = files[0];
Console.WriteLine(fullFilenameAndPath);
}
From the crippled file path you can get the directory path and the file name:
string path = Path.GetDirectoryName(filename);
string name = Path.GetFileName(filename);
Then you can get all files that matches the file name with any extension:
FileInfo[] found = new DirectoryInfo(path).GetFiles(name + ".*");
If the array contains one item, you have your match. If there is more than one item, you have to decide which one to use, or what to do with them.
All the pieces are here in the existing answers, but just trying to unify them into one answer for you - given the "guaranteed unique" declaration you're working with, you can toss in a FirstOrDefault since you don't need to worry about choosing among multiple potential matches.
static void Main(string[] args)
{
var match = FindMatch(args[0]);
Console.WriteLine("Best match for {0} is {1}", args[0], match ?? "[None found]");
}
private static string FindMatch(string pathAndFilename)
{
return FindMatch(Path.GetDirectoryName(pathAndFilename), Path.GetFileNameWithoutExtension(pathAndFilename));
}
private static string FindMatch(string path, string filename)
{
return Directory.GetFiles(path, filename + ".*").FirstOrDefault();
}
Output:
> ConsoleApplication10 c:\temp\bogus
Best match for c:\temp\bogus is [None found]
> ConsoleApplication10 c:\temp\7z465
Best match for c:\temp\7z465 is c:\temp\7z465.msi
> ConsoleApplication10 c:\temp\boot
Best match for c:\temp\boot is c:\temp\boot.wim