Enumerate contents of specific folder DotNetZip, without child folders - c#

Using Ionic.Zip
I wish to display the files or folders in a specific folder. I am using the SelectEntries method, but it unfortunately is filtering out the folders. Not what I was expecting using '*'.
ICollection<ZipEntry> selectEntries = _zipFile.SelectEntries("*",rootLocation)
If I follow an alternative approach:
IEnumerable<ZipEntry> selectEntries = _zipFile.Entries.Where(e => e.FileName.StartsWith(rootLocation))
I face two problems:
I have to switch '/' for '\' potentially.
I get all the subfolders.
Which is not desirable.
Anyone know why SelectEntries returns no folders, or am I misusing it?

I found a solution in my particular case. I think something about the way the Zipfile was constructed led to it appearing to have folders but none actually existed i.e. the following code yielded an empty list.
_zipFile.Entries.Where(e=>e.IsDirectory).AsList(); // always empty!
I used the following snippet to achieve what I needed. The regex is not as comprehensive as it should be but worked for all cases I needed.
var conformedRootLocation = rootLocation.Replace('\\','/').TrimEnd('/') + "/";
var pattern = string.Format(#"({0})([a-z|A-Z|.|_|0-9|\s]+)/?", conformedRootLocation);
var regex = new Regex(pattern);
return _zipFile.EntryFileNames.Select(e => regex.Match(e))
.Where(match => match.Success)
.Select(match => match.Groups[2].Value)
.Distinct()
.Select(f => new DirectoryResource
{
Name = f, IsDirectory = !Path.HasExtension(f)
})
.ToList();

Related

LINQ Query Not Selecting Files

I am trying to LINQ query a set of files where I can find the file names with a specific string in them.
I was using:
var docs = directory.enumerateFiles(searchFolder, "* " + strNumber+ "*", SearchOption.AllDirectories);
That was working fine, but some of my file searches were taking 30+ minutes due to the fact that one of the directories has 1+ million files. I was hoping to speed up the search process with a PLINQ query. However, while my syntax is good, I'm not getting the results I would expect. It looks like my problem may be in the Where statement. Any help would be helpful.
foreach (strNumber in strNumbers)
{
DirectoryInfo searchDirectory = new DirectoryInfo(searchFolder);
IEnumerable<System.IO.FileInfo> allDocs = searchDirectory.EnumerateFiles("*", SearchOPtion.AllDirectories);
IEnumerable<System.IO.FileInfo> docsToProcess = strNumbers
.SelectMany(strNumber => allDocs
.Where(file => file.Name.Contains(strNumber)))
.Distinct();
}
Any help would be much appreciated.
I would change the order of the problem.
Create a list of all files (into memory)
Perform the search over the memory list
Then, you can use a Parallel Foreach over the memory array and your disk usage is limited to the initial search.
var searchDirectory = new DirectoryInfo(searchFolder);
var allDocs = searchDirectory.EnumerateFiles("*", SearchOPtion.AllDirectories).ToArray();
// For extra points, use a Parallel.ForEach here for multi-threaded work
Parallel.Foreach(strNumbers, strNumber =>
{
// Work on allDocs here, it should be in memory
});

What's the best way to fiil list <string>?

I have a method, the input of which is a list of file addresses that I want to open this files and process it. this address contains the file extension. I know for sure that I have 3 file extensions (txt, xlsx, xls)
in the code pathWithFilesName it input list with file path;
then I want to send them to methods that will open and process them
pathWithFilesName.Add("ds.xlsx");
pathWithFilesName.Add("ds.txt");
var listExcel=new List<string>();
var listTxt= new List<string>();
var validExcelFileTypes = new List<string>{ ".xls", ".xlsx" };
foreach (var path in pathWithFilesName)
{
foreach (var valid in validExcelFileTypes)
{
if (path.EndsWith(valid))
{
listExcel.Add(path);
}
else
{
listTxt.Add(path);
}
}
}
this variant not optimal at all but work)
i know how take excel files on link
var list= (from path in pathWithFilesName from valid in validExcelFileTypes where path.EndsWith(valid) select path).ToList();
but with this approach I need then compare 2 lists. for example some kind of Intersect
what is the best way to make a sample?
Here is a variation using LinQ and lambda. It should not be more efficient not better or worse. It may be more readable.
The listExcel can be find that way :
var listExcel = pathWithFilesName.Where(path=>validExcelFileTypes.Any(ext=> path.EndsWith(ext)));
Enumerable.Any
Enumerable.Where
If you need both list in one go. You can group the source on the same condition:
var listGrp = pathWithFilesName.GroupBy(path=>validExcelFileTypes.Any(ext=> path.EndsWith(ext)));
You can use MoreLinQ Partition: "Partitions a sequence by a predicate,..".
var (listExcel, listTxt) = pathWithFilesName
.Partition(p =>
validExcelFileTypes.Any(ext => p.EndsWith(ext))
);
Under the hood it's just a GroupBy source code. Unrolled into a Named Tuple.
Live demo

How to get the files of remote directory using a pattern with C# and WinSCP

I'm trying to get an specific files from a remote server with FTP/SFTP connection, the issue that I'm having is, I'm trying to get the count of files in the remote directory with an specific pattern. I'm using a mask but is not working for me, it throwing an exception:
this is what I have
DataFile.sRemoteDirectory = "/user/ftpuser/test/";
receivepattern = "Del*";
filesCount =
session.ListDirectory(
session.EscapeFileMask(DataFile.sRemoteDirectory + receivepattern))
.Files.Where(x => !x.IsDirectory).Count();
The Session.ListDirectory method does not accept a wildcard, only a path.
Since, the WinSCP .NET assembly 5.9, you can use the Session.EnumerateRemoteFiles method instead:
filesCount =
session.EnumerateRemoteFiles(
DataFile.sRemoteDirectory, receivepattern, EnumerationOptions.None).Count();
In older versions, you have to filter the files returned by the Session.ListDirectory yourself:
Regex r = new Regex("^Del.*");
filesCount = session.ListDirectory(DataFile.sRemoteDirectory).Files
.Where(x => !x.IsDirectory)
.Where(x => r.Match(x.Name))
.Count()
See the official example Listing files matching wildcard (in PowerShell though).
This is what I did and it work! hope to someone help this piece of code, I used regular expression, where receivepattern is the pattern used:
receivepattern = "^[\\d\\w]*" + receivepattern;
r = new Regex(receivepattern);
filesCount = session.ListDirectory(DataFile.sRemoteDirectory).Files.Where(x => !x.IsDirectory).Where(x => r.IsMatch(x.Name)).Count();

C#: Get the 5 newest (last modified) files from a directory

Is there a way I can store the file location of the 5 last modified files from a directory using Array?
I am currently using the following codes below to get the last file:
DateTime lastHigh = new DateTime(1900,1,1);
string highDir;
foreach (string subdir in Directory.GetDirectories(path)){
DirectoryInfo fi1 = new DirectoryInfo(subdir);
DateTime created = fi1.LastWriteTime;
if (created > lastHigh){
highDir = subdir;
lastHigh = created;
}
}
I'll be using Array to send multiple files to an email address as attachment.
UPDATE
I am currently using the codes below to get the last modified files after 1 minute:
string myDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),
"Test Folder");
var directory = new DirectoryInfo(myDirectory);
DateTime from_date = DateTime.Now.AddMinutes(-1);
DateTime to_date = DateTime.Now;
var files = directory.GetFiles().Where(file => file.LastWriteTime >= from_date && file.LastWriteTime <= to_date);
I want to store to list of file names coming from files
Here's a general way to do this with LINQ:
Directory.GetFiles(path)
.Select(x => new FileInfo(x))
.OrderByDescending(x => x.LastWriteTime)
.Take(5)
.ToArray()
I suspect this isn't quite what you want, since your code examples seem to be working at different tasks, but in the general case, this would do what the title of your question requests.
It sounds like you want a string array of the full filepaths of all the files in a directory.
Given you already have your FileInfo enumerable, you can do this:
var filenames = files.Select(f => f.FullName).ToArray();
If you wanted just the filenames, replace FullName with Name.
While the answer Paul Phillips provided worked. It's worth to keep in mind that the
FileInfo.LastWriteTime & FileInfo.LastAccessTime do not always work. It depends on how the OS is configured or could be a caching issue.
.NET FileInfo.LastWriteTime & FileInfo.LastAccessTime are wrong
File.GetLastWriteTime seems to be returning 'out of date' value

How to check if filename contains substring in C#

I have a folder with files named
myfileone
myfiletwo
myfilethree
How can I check if file "myfilethree" is present.
I mean is there another method other than IsFileExist() method, i.e like filename contains substring "three"?
Substring:
bool contains = Directory.EnumerateFiles(path).Any(f => f.Contains("three"));
Case-insensitive substring:
bool contains = Directory.EnumerateFiles(path).Any(f => f.IndexOf("three", StringComparison.OrdinalIgnoreCase) > 0);
Case-insensitive comparison:
bool contains = Directory.EnumerateFiles(path).Any(f => String.Equals(f, "myfilethree", StringComparison.OrdinalIgnoreCase));
Get file names matching a wildcard criteria:
IEnumerable<string> files = Directory.EnumerateFiles(path, "three*.*"); // lazy file system lookup
string[] files = Directory.GetFiles(path, "three*.*"); // not lazy
If I understand your question correctly, you could do something like
Directory.GetFiles(directoryPath, "*three*")
or
Directory.GetFiles(directoryPath).Where(f => f.Contains("three"))
Both of these will give you all the names of all files with three in it.
I am not that familiar with IO but maybe this would work ? Requires using System.Linq
System.IO.Directory.GetFiles("PATH").Where(s => s.Contains("three"));
EDIT: Note that this returns array of strings.

Categories