I have this test path:
private static string dCrawler = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "TestLetters";
Is there a way to say:
foreach (item in dCrawler)
{
if (item.isFile)
{
// check file info date modified code
} else
{
foreach (fileinfo file in ...
}
}
so far I have only found ways to check a file in a directory. Is the only way to do it by having two separate loops one for files and one for folders?
You can use Directory.GetFiles(); that returns a string[] and use the string value to create your FileInfo. Like this
foreach (string n in Directory.GetFiles(dCrawler))
{
FileInfo b = new FileInfo(n);
}
To get directories, you can similarly use Directory.GetDirectories();
foreach (string n in Directory.GetDirectories(dCrawler))
{
DirectoryInfo b = new DirectoryInfo(n);
}
Related
I have a unity project that i need to rename basically all my files in it to contain a - as a way of easily identifying what assetbundle i need to load it from.
I would need to insert a - at the end of the identifier so for example, testtest.png would become test-test.png and so on.
I currently have this (just want to get the identifier from the file name itself for now) however, the first string in temp is always empty with the second one containing the rest of the file name
foreach (string file in Directory.GetFiles(Directory.GetCurrentDirectory()))
{
string name = file.Split('\\').Last();
if (name.StartsWith(args[0]))
{
string[] temp = name.Split(new[]{args[0]},StringSplitOptions.None);
foreach (string s in temp)
{
Console.WriteLine(s);
}
}
}
D:\renamething\bin\Debug>renamething.exe test
.pdb
I tried Regex for it as well however it produced the same result, empty string in the first one, rest of it in the second.
I don't think that would work, especially the args[0]
Try this:
foreach (string file in Directory.GetFiles(Directory.GetCurrentDirectory()))
{
var fileInfo = new FileInfo(file); //Get FileInfo
if (!fileInfo.Name.StartsWith(args[0], StringComparison.OrdinalIgnoreCase)) //If File doesn't start with the specified arguments, don't process
{
continue;
}
//Consider file -> C:/TestFolder/test.png
var directory = fileInfo.DirectoryName;//Gives C:\TestFolder\
var extension = fileInfo.Extension; //gives ".png"
var fileName = Path.GetFileNameWithoutExtension(fileInfo.Name); //Gives "test"
var modifiedFileName = $"{fileName}-test{extension}"; //Gives "test-test.png
var modifiedFullPath = $"{directory}/{modifiedFileName}";// C:\TestFolder\test-test.png
fileInfo.MoveTo(modifiedFullPath);
}
With the code from #Zee (and #Dai from having a second look over), here is what i ended up in the odd chance that anyone else in the future comes here and needs it
public static void Main(string[] args){
foreach(string file in Directory.GetFiles(Directory.GetCurrentDirectory())){
FileInfo fileInfo=new FileInfo(file);
if(fileInfo.Name.StartsWith(args[0])&&fileInfo.Name.EndsWith(".png"){
string[]temp=Regex.Split(fileInfo.Name, #"(?<!^)(?=[A-Z])");
temp[0]+="-";
File.Move(fileInfo.FullName,String.Concat(temp));
}
}
}
I'm struggling with this basic operation.It will be nice if someone can write a working code.So let's say I got folder "AB" on desktop.Folder AB contains subfolder A and subfolder B.Subfolder A contains A.txt and Subfolder B contains B.txt.I want the user to simply choose folder AB via a browser dialog(I did that already) and then,when he clicks on a checkbox,file A.txt will go on subfolder B and B.txt will go on subfolder A.
I will do this for simple folders A and B. You will have to consider the chances of sub-folders as well.
string[] filesA = System.IO.Directory.GetFiles(AsourcePath);
string[] filesB = System.IO.Directory.GetFiles(BsourcePath);
foreach (string s in filesA)
{
System.IO.File.Move(s, AsourcePath);
}
foreach (string s in filesB)
{
System.IO.File.Move(s, BsourcePath);
}
Please Note: You will have consider so many scenarios for this including sub-folders, overwriting, existing files or folders etc.
Assuming that you have the folder path for both A and B folders,
var Afolder = #"D:\AB\A";
var Bfolder = #"D:\AB\B";
SwapFolderFiles(Afolder, Bfolder);
Pass the folder path for both A and B to SwapFolderFiles,
private static void SwapFolderFiles(string AFolder, string BFolder)
{
var AFolderfiles = System.IO.Directory.GetFiles(AFolder);
var BFolderfiles = System.IO.Directory.GetFiles(BFolder);
MoveFiles(AFolder, BFolder, AFolderfiles);
MoveFiles(BFolder, AFolder, BFolderfiles);
}
private static void MoveFiles(string sourceFolder, string destinationFolder, string[] folderfiles)
{
foreach (var file in folderfiles)
{
var filename = file.Substring(file.LastIndexOf("\\")+1);
var source = System.IO.Path.Combine(sourceFolder, filename);
var destination = System.IO.Path.Combine(destinationFolder, filename);
System.IO.File.Move(source, destination);
}
}
I need help adding current logged %USER% to the path, this is my code so far:
DirectoryInfo dir = new DirectoryInfo(#"%USERPROFILE%\Local Settings\TEST");
foreach (FileInfo files in dir.GetFiles())
{
files.Delete();
}
foreach (DirectoryInfo dirs in dir.GetDirectories())
{
dirs.Delete(true);
}
how can I make him read %USERPROFILE% as current user?
I would love an example to figure things out, btw I want to use it to delete C:\Document and settings\%USERPFORILE%\Local Settings\Temp
Just wanted to add that while Environment.SpecialFolder.UserProfile is a good answer to your specific question, there's also another option that works for all environment variables, not just those that have a SpecialFolder accessor: Environment.ExpandEnvironmentVariables.
It will take a string, like your #"%USERPROFILE%\Local Settings\TEST", and return a new string with all %% environment variables expanded.
How about this:
void Main()
{
string userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string subFolder = #"Local Settings\TEST";
string path = Path.Combine(userProfile, subFolder);
DirectoryInfo di = new DirectoryInfo(path);
if (di.Exists)
{
Console.WriteLine("Deleting " + di);
di.Delete(true);//recursive
}
else
{
Console.WriteLine("Directory " + di + " was not found");
}
}
I think that this is what you actually want:
String appData =
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
Use that instead of the Code Local Setting folder if you want to store data or do something.
(as my comment said, the Local setting folder is protected and that way you won't be able to open it)
The best way is to use Environment.ExpandEnvironmentVariables
void Main() {
string path = Environment.ExpandEnvironmentVariables(#"%USERPROFILE%\Local Settings\TEST");
DirectoryInfo dir = new DirectoryInfo(path);
foreach (FileInfo files in dir.GetFiles())
{
files.Delete();
}
foreach (DirectoryInfo dirs in dir.GetDirectories())
{
dirs.Delete(true);
}
}
https://msdn.microsoft.com/en-us/library/system.environment.expandenvironmentvariables.aspx
here is my code:
private static void TreeScan(string sDir)
{
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d))
{
//Save file f
}
}
TreeScan(d, client);
}
The problem is that it doesn't get the FILES of the sDir (Starting Directory) it only gets the Folders and the Files in the Sub Folders.
How can I make it get the files from the sDir too ?
Don't reinvent the wheel, use the overload of GetFiles that allows you to specify that it searches subdirectories.
string[] files
= Directory.GetFiles(path, searchPattern, SearchOption.AllDirectories);
private static void TreeScan( string sDir )
{
foreach (string f in Directory.GetFiles( sDir ))
{
//Save f :)
}
foreach (string d in Directory.GetDirectories( sDir ))
{
TreeScan( d );
}
}
There are some problems with your code. For one, the reason you never saw the files from the root folder is because your recursed before doing and file reads. Try this:
public static void Main()
{
TreeScan(#"C:\someFolder");
}
private static void TreeScan(string sDir)
{
foreach (string f in Directory.GetFiles(sDir))
Console.WriteLine("File: " + f); // or some other file processing
foreach (string d in Directory.GetDirectories(sDir))
TreeScan(d); // recursive call to get files of directory
}
You have to use
Directory.GetFiles(targetDirectory);
like in This sample, wich contains a complete implementation of what you're looking for
Your GetFiles loop should be outside the GetDirectories loop. And shouldn't your TreeScan stay inside GetDirectories loop? In short the code should look like this:
private static void TreeScan(string sDir)
{
foreach (string d in Directory.GetDirectories(sDir))
{
TreeScan(d, client);
}
foreach (string f in Directory.GetFiles(d))
{
//Save file f
}
}
If using Fx4 and above the EnumerateFiles method will return all files with efficient memory management, whereas GetFiles can require max resources on big directories (or drives).
var files = Directory.EnumerateFiles(dir.Path, "*.*");
Listing all files in a drive other than my system drive throws an UnauthorizedAccessException.
How can I solve this problem?
Is there a way to grant my application the access it needs?
My code:
Directory.GetFiles("S:\\", ...)
Here's a class that will work:
public static class FileDirectorySearcher
{
public static IEnumerable<string> Search(string searchPath, string searchPattern)
{
IEnumerable<string> files = GetFileSystemEntries(searchPath, searchPattern);
foreach (string file in files)
{
yield return file;
}
IEnumerable<string> directories = GetDirectories(searchPath);
foreach (string directory in directories)
{
files = Search(directory, searchPattern);
foreach (string file in files)
{
yield return file;
}
}
}
private static IEnumerable<string> GetDirectories(string directory)
{
IEnumerable<string> subDirectories = null;
try
{
subDirectories = Directory.EnumerateDirectories(directory, "*.*", SearchOption.TopDirectoryOnly);
}
catch (UnauthorizedAccessException)
{
}
if (subDirectories != null)
{
foreach (string subDirectory in subDirectories)
{
yield return subDirectory;
}
}
}
private static IEnumerable<string> GetFileSystemEntries(string directory, string searchPattern)
{
IEnumerable<string> files = null;
try
{
files = Directory.EnumerateFileSystemEntries(directory, searchPattern, SearchOption.TopDirectoryOnly);
}
catch (UnauthorizedAccessException)
{
}
if (files != null)
{
foreach (string file in files)
{
yield return file;
}
}
}
}
You can the use it like this:
IEnumerable<string> filesOrDirectories = FileDirectorySearcher.Search(#"C:\", "*.txt");
foreach (string fileOrDirectory in filesOrDirectories)
{
// Do something here.
}
It's recursive, but the use of yield gives it a low memory footprint (under 10KB in my testing). If you want only files that match the pattern and not directories as well just replace EnumerateFileSystemEntries with EnumerateFiles.
Are you allowed to access the drive? Can the program access the drive when it's not run from Visual Studio? Are restrictive permissions defined in the project's Security page ("Security Page, Project Designer")?
In .net core you can do something like this below. It can search for all subdirectories recursively with good performance and ignoring paths without access.
I also tried other methods found in
How to quickly check if folder is empty (.NET)? and
Is there a faster way than this to find all the files in a directory and all sub directories? and
https://www.codeproject.com/Articles/1383832/System-IO-Directory-Alternative-using-WinAPI
public static IEnumerable<string> ListFiles(string baseDir)
{
EnumerationOptions opt = new EnumerationOptions();
opt.RecurseSubdirectories = true;
opt.ReturnSpecialDirectories = false;
//opt.AttributesToSkip = FileAttributes.Hidden | FileAttributes.System;
opt.AttributesToSkip = 0;
opt.IgnoreInaccessible = true;
var tmp = Directory.EnumerateFileSystemEntries(baseDir, "*", opt);
return tmp;
}
I solved the problem. Not really but at least the source.
It was the SearchOption.AllDirectories option that caused the exception.
But when I just list the immediate files using Directories.GetFiles, it works.
This is good enough for me.
Any way to solve the recursive listing problem?