Excluded several extension c# - c#

How can I exclude all .txt file and doc file in a folder?
I am able to get all the file but unable to exclude .txt file and .doc files.
foreach (string f in Directory.GetFiles(#readpath))
{
List<string> list = new List<string>();
list.Add(f);
for (listcount = 0; listcount < list.Count; listcount++)
{
path2 = list[listcount];
creationdate = File.GetCreationTime(path2);
modidate = File.GetLastWriteTime(path2);
}
chkchecksum();
}

Replace
foreach (string f in Directory.GetFiles(#readpath))
With
foreach (string f in Directory.GetFiles(#readpath).Where(f => !(f.EndsWith(".doc", StringComparison.OrdinalIgnoreCase) && !f.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))))

Related

How to sort a text file using c#

First I'm a very Beginner in c#, and Sorry for my english
I'm trying to sort myfile:"D:\Test.txt" by the number sfter the first "|"
FROM :
AVDT353|180 |||14/01/2021||
GSDF445|10 |||14/01/2021||
MLKLMK6|17023 |||14/01/2021||
TO :
GSDF445|10 |||14/01/2021||
AVDT353|180 |||14/01/2021||
MLKLMK6|17023 |||14/01/2021||
First, load the text file. Then, create a list of strings by using line breaks as the delimiter. Next, sort the lines using Linq, splitting after the | character. Finally, write the strings to file, putting each on a new line.
string contents = File.ReadAllText(#"D:\Test.tx");
var lines = contents.Split(Environment.NewLine).ToList();
var sorted = lines.OrderBy(l => l.Split("|")[1]).ToList();
// To update the content of the file:
File.WriteAllText(#"D:\Out.tx", string.Join(Environment.NewLine, sorted));
void SortFile()
{
DirectoryInfo d = new DirectoryInfo(#"D:\Test");//Assuming Test is your Folder
FileInfo[] Files = d.GetFiles("*.txt"); //Getting Text files
string str = "";
foreach (FileInfo file in Files)
{
int fileNo = Convert.ToInt32(file.Name.Split('|')[1]);
for (int i = 0; i < Files.Length; i++)
{
if (fileNo < Convert.ToInt32((Files[i].Name.Split('|')[1])))
{
//Add it to list or something
}
}
}
}

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;
}
}
}

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 to find the Filename with the latest version in C#

I have a folder that is filled with dwg files so I just need to find the latest version of a File or if a File has no versions then copy it to a directory. For example here are three files:
ABBIE 08-10 #6-09H4 FINAL 06-12-2012.dwg
ABBIE 08-10 #6-09H4 FINAL 06-12-2012_1.dwg
ABBIE 08-10 #6-09H4 FINAL 06-12-2012_2.dwg
Notice the difference is one file has a _1 and another has a _2 so the latest file here is the _2. I need to keep the latest file and copy it to a directory. Some files will not have different versions so those can be copied. I cannot focus on the creation date of the file or the modified date because in many instances they are the same so all I have to go on is the file name itself. I'm sure there is a more efficient way to do this than what I will post below.
DirectoryInfo myDir = new DirectoryInfo(#"H:\Temp\Test");
var Files = myDir.GetFiles("*.dwg");
string[] fileList = Directory.GetFiles(#"H:\Temp\Test", "*FINAL*", SearchOption.AllDirectories);
ArrayList list = new ArrayList();
ArrayList WithUnderscores = new ArrayList();
string nameNOunderscores = "";
for (int i = 0; i < fileList.Length; i++)
{
//Try to get just the filename..
string filename = fileList[i].Split('.')[0];
int position = filename.LastIndexOf('\\');
filename = filename.Substring(position + 1);
filename = filename.Split('_')[0];
foreach (FileInfo allfiles in Files)
{
var withoutunderscore = allfiles.Name.Split('_')[0];
withoutunderscore = withoutunderscore.Split('.')[0];
if (withoutunderscore.Equals(filename))
{
nameNOunderscores = filename;
list.Add(allfiles.Name);
}
}
//If there is a number after the _ then capture it in an ArrayList
if (list.Count > 0)
{
foreach (string nam in list)
{
if (nam.Contains("_"))
{
//need regex to grab numeric value after _
var match = new Regex("_(?<number>[0-9]+)").Match(nam);
if (match.Success)
{
var value = match.Groups["number"].Value;
var number = Int32.Parse(value);
WithUnderscores.Add(number);
}
}
}
int removedcount = 0;
//Whats the max value?
if (WithUnderscores.Count > 0)
{
var maxval = GetMaxValue(WithUnderscores);
Int32 intmax = Convert.ToInt32(maxval);
foreach (FileInfo deletefile in Files)
{
string shorten = deletefile.Name.Split('.')[0];
shorten = shorten.Split('_')[0];
if (shorten == nameNOunderscores && deletefile.Name != nameNOunderscores + "_" + intmax + ".dwg")
{
//Keep track of count of Files that are no good to us so we can iterate to next set of files
removedcount = removedcount + 1;
}
else
{
//Copy the "Good" file to a seperate directory
File.Copy(#"H:\Temp\Test\" + deletefile.Name, #"H:\Temp\AllFinals\" + deletefile.Name, true);
}
}
WithUnderscores.Clear();
list.Clear();
}
i = i + removedcount;
}
else
{
//This File had no versions so it is good to be copied to the "Good" directory
File.Copy(#"H:\Temp\SH_Plats\" + filename, #"H:\Temp\AllFinals" + filename, true);
i = i + 1;
}
}
I've made a Regex based solution, and apparently come late to the party in the meantime.
(?<fileName>[A-Za-z0-9-# ]*)_?(?<version>[0-9]+)?\.dwg
this regex will recognise the fileName and version and split them into groups, a pretty simple foreach loop to get the most recent files in a dictionary (cos I'm lazy) and then you just need to put the fileNames back together again before you access them.
var fileName = file.Key + "_" + file.Value + ".dwg"
full code
var files = new[] {
"ABBIE 08-10 #6-09H4 FINAL 06-12-2012.dwg",
"ABBIE 08-10 #6-09H4 FINAL 06-12-2012_1.dwg",
"ABBIE 08-10 #6-09H4 FINAL 06-12-2012_2.dwg",
"Second File.dwg",
"Second File_1.dwg",
"Third File.dwg"
};
// regex to split fileName from version
var r = new Regex( #"(?<fileName>[A-Za-z0-9-# ]*)_?(?<version>[0-9]+)?\.dwg" );
var latestFiles = new Dictionary<string, int>();
foreach (var f in files)
{
var parsedFileName = r.Match( f );
var fileName = parsedFileName.Groups["fileName"].Value;
var version = parsedFileName.Groups["version"].Success ? int.Parse( parsedFileName.Groups["version"].Value ) : 0;
if( latestFiles.ContainsKey( fileName ) && version > latestFiles[fileName] )
{
// replace if this file has a newer version
latestFiles[fileName] = version;
}
else
{
// add all newly found filenames
latestFiles.Add( fileName, version );
}
}
// open all most recent files
foreach (var file in latestFiles)
{
var fileToCopy = File.Open( file.Key + "_" + file.Value + ".dwg" );
// ...
}
You can use this Linq query with Enumerable.GroupBy which should work(now tested):
var allFiles = Directory.EnumerateFiles(sourceDir, "*.dwg")
.Select(path => new
{
Path = path,
FileName = Path.GetFileName(path),
FileNameWithoutExtension = Path.GetFileNameWithoutExtension(path),
VersionStartIndex = Path.GetFileNameWithoutExtension(path).LastIndexOf('_')
})
.Select(x => new
{
x.Path,
x.FileName,
IsVersionFile = x.VersionStartIndex != -1,
Version = x.VersionStartIndex == -1 ? new Nullable<int>()
: x.FileNameWithoutExtension.Substring(x.VersionStartIndex + 1).TryGetInt(),
NameWithoutVersion = x.VersionStartIndex == -1 ? x.FileName
: x.FileName.Substring(0, x.VersionStartIndex)
})
.OrderByDescending(x => x.Version)
.GroupBy(x => x.NameWithoutVersion)
.Select(g => g.First());
foreach (var file in allFiles)
{
string oldPath = Path.Combine(sourceDir, file.FileName);
string newPath;
if (file.IsVersionFile && file.Version.HasValue)
newPath = Path.Combine(versionPath, file.FileName);
else
newPath = Path.Combine(noVersionPath, file.FileName);
File.Copy(oldPath, newPath, true);
}
Here's the extension method which i'm using to determine if a string is parsable to int:
public static int? TryGetInt(this string item)
{
int i;
bool success = int.TryParse(item, out i);
return success ? (int?)i : (int?)null;
}
Note that i'm not using regex but string methods only.
Try this
var files = new My.Computer().FileSystem.GetFiles(#"c:\to\the\sample\directory", Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, "*.dwg");
foreach (String f in files) {
Console.WriteLine(f);
};
NB: Add a reference to Microsoft.VisualBasic and use the following line at the beginning of the class:
using My = Microsoft.VisualBasic.Devices;
UPDATE
The working sample[tested]:
String dPath=#"C:\to\the\sample\directory";
var xfiles = new My.Computer().FileSystem.GetFiles(dPath, Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, "*.dwg").Where(c => Regex.IsMatch(c,#"\d{3,}\.dwg$"));
XElement filez = new XElement("filez");
foreach (String f in xfiles)
{
var yfiles = new My.Computer().FileSystem.GetFiles(dPath, Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, string.Format("{0}*.dwg",System.IO.Path.GetFileNameWithoutExtension(f))).Where(c => Regex.IsMatch(c, #"_\d+\.dwg$"));
if (yfiles.Count() > 0)
{
filez.Add(new XElement("file", yfiles.Last()));
}
else {
filez.Add(new XElement("file", f));
};
};
Console.Write(filez);
Can you do this by string sort? The only tricky part I see here is to convert the file name to a sortable format. Just do a string replace from dd-mm-yyyy to yyyymmdd. Then, sort the the list and get the last record out.
This is what you want considering fileList contain all file names
List<string> latestFiles=new List<string>();
foreach(var groups in fileList.GroupBy(x=>Regex.Replace(x,#"(_\d+\.dwg$|\.dwg$)","")))
{
latestFiles.Add(groups.OrderBy(s=>Regex.Match(s,#"\d+(?=\.dwg$)").Value==""?0:int.Parse(Regex.Match(s,#"\d+(?=\.dwg$)").Value)).Last());
}
latestFiles has the list of all new files..
If fileList is bigger,use Threading or PLinq

How to get files from exact subdirectories

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));
}

Categories

Resources