converting filenames to lower case - c#

was hoping for some advice as to how to convert existing file names in a folder...all to lower case.
I felt that a good start would be to save the file names in a list and convert them all to lower.
How can I replace the existing file names in the folder to the lower case ones?
List<string> codes = new List<string>();
string[]productCodes = Directory.GetFiles(#"C:\Users\Ariang\Desktop\screenshotslowercase\screenshots");
codes = productCodes.ToList();
codes = codes.ConvertAll(t => t.ToLower());

This should work:
foreach (var file in Directory.GetFiles(#"C:\Temp\testrename"))
{
File.Move(file, file.ToLowerInvariant());
}
A few notes, first of all I have tested this and it works, somebody else mentioned using a temporary variable, but I haven't needed to do this.
Also, I have run this multiple times on the same directory, and I don't get an IOException the second or third time around, so I don't think any additional checking is necessary.
However, I am on Windows 8 and targeting .Net 4.5, things may be different on earlier versions of Windows or .Net.

Windows system doesn't see difference betweeen lower and upper letters in file names. Thats why you can't convert like "MyFile" -> "myfile". Use two steps instead:
foreach (var file in Directory.GetFiles(#"C:\Temp\testrename"))
{
var tempName = "." + file.ToLowerInvariant();
File.Move(file, tempName);
File.Move(tempName, file.ToLowerInvariant());
}

no need for list and all that. Simple read the file name from directory and use
System.IO.File.Move("oldfilename", "oldfilename".ToLower());
string[] files = Directory.GetFiles(dir);
foreach(string file in files)
{
System.IO.File.Move(file, file.ToLowerInvariant());
}

Related

Reading a specific time file and writing the contents to another one

At runtime, I want to read all files who has the time stamp of a particular time. For example: if the application is running at 11:00:--, then it should read all files which is created after 11:00:00 till now(excluding the present one) and must write in the present file..I have tried like:
string temp_file_format = "ScriptLog_" + DateTime.Now.ToString("dd_MM_yyyy_HH");
string path = #"C:\\ScriptLogs";
var all_files = Directory.GetFiles(path, temp_file_format).SelectMany(File.ReadAllLines);
using (var w = new StreamWriter(logpath))
foreach (var line in all_files)
w.WriteLine(line);
But, this doesn't seems to be working.No error..No exception..But it doesn't read the files, while it exist.
The pattern parameter of the GetFiles method should probably also include a wildcard, something like:
string temp_file_format = "ScriptLog_" + DateTime.Now.ToString("dd_MM_yyyy_HH") + "*";
This will match all files starting with "ScriptLog_13_09_2013_11"
As #Edwin already solved your problem, I'd just like to add a suggestion regarding your code (mostly performance related).
Since you are only reading these lines in order to write them to a different file and discard them from memory, you should consider using File.ReadLines instead of File.ReadAllLines, because the latter method loads all lines from each file into memory unnecessarily.
Combine this with the File.WriteAllLines method, and you can simplify your code while reducing memory pressure to:
var all_files = Directory.GetFiles(path, temp_file_format);
// File.ReadLines returns a "lazy" IEnumerable<string> which will
// yield lines one by one
var all_lines = all_files.SelectMany(File.ReadLines);
// this iterates through all_lines and writes them to logpath
File.WriteAllLines(logpath, all_lines);
All that can even be written as a one-liner (that is, if you are not paid by your source code line count). ;-)

How to keep a TXT file synced with a List<string>

So, I'm making a text based game in C#, and I am creating a profile feature. It already creates a new TXT file when it is executed for the first time and stores it in the appdata folder. Now, here is what is in that TXT file;
NAME=[$]
REP=[0]
The 'NAME' operator is for a personal alias, and is what I am working on at the moment. What I need it to do, is upon entering a command;
alias Example
It will modify a List which contains exactly that, in short, synced with the TXT file. I have tried many, many different ways, including;
case "alias":
string joined = string.Join(",", profileList.ToArray());
string[] joineone = joined.Split(',');
profileList.Clear();
foreach (string var in joineone)
{
if (var.StartsWith("NAME"))
{
var.Replace(getStringBetween(var, "[", "]"), preCut[1]);
}
profileList.Add(var);
}
Invoke(new _rewriteProfile(rewriteProfile));
break;
and a much shorter version;
profileList[0].Replace(getStringBetween(profileList[0],"=[", "]"), preCut[1]);
Where profileList is the synced one with the TXT file and getStringBetween gets a string between two characters. It is also hooked up to a replace, to replace it with the first "cut", which in this case is 'Example'. The thing is, it never changes. The text just does not change in the list. I have NO IDEA why. I am using .NET 2.0 by the way.
Any help would be highly appreciated!
var = var.Replace(getStringBetween(var, "[", "]"), preCut[1]);
Check if the txt file is read only...... or maybe your method (getStringBetween) does not return any thing.

How to remove a line from a file without overwriting the contents in a new file

FileName="1.pdf",filepath="f:/test1"
FileName="2.pdf",filepath="f:/test2"
FileName="3.pdf",filepath="f:/test3"
FileName="4.pdf",filepath="f:/test4"
FileName="5.pdf",filepath="f:/test5"
FileName="6.pdf",filepath="f:/test6"
I don't want to create a new file. Overwriting in a same file is ok
I tried the following.
var reader = File.OpenText("f:/test5");
reader. // ?
I don't know what to put after reader. If any alternate way is there, provide me a solution.I want to remove only a particular line based on the unique file name. If I am having 5.pdf as the filename, then I need to delete or remove the entire line which is "FileName="5.pdf"...line from the file. I don't want to overwrite the contents in a new file again. Provide me a solution. Thanks.
You cannot reomve a line from a textfile without rewriting the file. Do something like this
string filename =
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),
"Test1.txt");
string[] lines = File.ReadAllLines(filename);
var list = new List<string>(lines);
list.RemoveAt(4);
File.WriteAllLines(filename, list.ToArray());
EDIT:
You can find a line with a specific filename like this:
int index = list.FindIndex(s => s.EndsWith("/test5\""));
// Or whatever test is appropriate.
if (index >= 0) {
list.RemoveAt(index);
File.WriteAllLines(filename, list.ToArray());
}
If you don't mind using gnu tools, you can use sed http://en.kioskea.net/faq/1451-sed-delete-one-or-more-lines-from-a-file
It's technically impossible, as much as I'm aware of, as OS will create a new IO artifact.(By the way not very sure on this) .
But what is much more important, that it's extremely dangerous. IO operations are subjects to fail, so you have to gurantee in some way consistency of your operations on file.
One of possible ways of doing this is:
write all lines, except those ones you want to skip, into the new TEMP file
rename your old file with some other temp name
rename fisrt TEMP file in name of previous file
delete original file.
No matter what utility you use or what code you write, the operating system will always create a new file to do it.

Deleting multiple files with wildcard

You know that in linux it's easy but I can't just understand how to do it in C# on Windows. I want to delete all files matching the wildcard f*.txt. How do I go about going that?
You can use the DirectoryInfo.EnumerateFiles function:
var dir = new DirectoryInfo(directoryPath);
foreach (var file in dir.EnumerateFiles("f*.txt")) {
file.Delete();
}
(Of course, you'll probably want to add error handling.)
I know this has already been answered and with a good answer, but there is an alternative in .NET 4.0 and higher. Use Directory.EnumerateFiles(), thus:
foreach (string f in Directory.EnumerateFiles(myDirectory,"f*.txt"))
{
File.Delete(f);
}
The disadvantage of DirectoryInfo.GetFiles() is that it returns a list of files - which 99.9% of the time is great. The disadvantage is if the folder contains tens of thousands of files (which is rare) then it becomes very slow and enumerating through the matching files is much faster.
You can use the Directory.GetFiles method with the wildcard overload. This will return all the filenames that match your pattern. You can then delete these files.
I appreciate this thread is a little old now, but if you want to use linq then
Directory.GetFiles("f:\\TestData", "*.zip", SearchOption.TopDirectoryOnly).ToList().ForEach(File.Delete);

Is there a wildcard expansion option for .net apps?

I've used the setargv.obj linking for Expanding Wildcard Arguments in the past for a number of C and C++ apps, but I can't find any similar mention for .net applications.
Is there a standard way to have your app's command line parameters automatically wildcard expanded? (i.e. expand *.doc from one entry in args parameter to all that match that wildcard).
P.S. I've hacked something together with Directory.GetFiles() for my current little project, but it does not cover wildcards with paths (yet), and it would be nice to do it without custom code.
Update: here is my rough hack, for illustration. It needs to split the parameters for the path and name for the GetFiles(), but this is a general idea. Linking setargv.obj into a C or C++ app would basically do all the wildcard expansion, leaving the user to only iterate over the argv array.
public static void Main(string[] args)
{
foreach (string argString in args)
{
// Split into path and wildcard
int lastBackslashPos = argString.LastIndexOf('\\') + 1;
path = argString.Substring(0, lastBackslashPos);
filenameOnly = argString.Substring(lastBackslashPos, argString.Length - lastBackslashPos);
string[] fileList = System.IO.Directory.GetFiles(path, filenameOnly);
foreach (string fileName in fileList)
{
// do things for each file
}
}
}
Here us my rough hack. I'd love for it to be recursive. And having experienced the shortcoming of Windows wildcards I might decide to use regular expressions rather than letting GetFiles() do it for me.
using System.IO;
public static string[] ExpandFilePaths(string[] args)
{
var fileList = new List<string>();
foreach (var arg in args)
{
var substitutedArg = System.Environment.ExpandEnvironmentVariables(arg);
var dirPart = Path.GetDirectoryName(substitutedArg);
if (dirPart.Length == 0)
dirPart = ".";
var filePart = Path.GetFileName(substitutedArg);
foreach (var filepath in Directory.GetFiles(dirPart, filePart))
fileList.Add(filepath);
}
return fileList.ToArray();
}
I'm not sure exactly what you're after... but if I get where you're going with the Directory.GetFiles() "hack" you mentioned, then something like this might work:
var Dirs = Directory.GetDirectories(#"C:\Windows", "sys*",
SearchOption.TopDirectoryOnly).ToList();
var Files = new List<String>();
Dirs.ForEach(dirName => Files.AddRange(Directory.GetFiles(dirName, "*.sys", SearchOption.AllDirectories)));
The wildcard option on the GetDirectories call will allow you to grab all the directories contained in the Windows folder [directly] that match the pattern "sys*".
You can then iterate over those folders grabbing all the files that match the pattern "*.sys".
Is that the kind of thing you're looking for? To automatically expand the args, you'd have to extract the wildcards in some kind of meaningful manner and apply them to that model...
For instance:
RunMyApp "C:\Windows\Sys*\ *.sys"
You'd pull out the string C:\Windows - probably with a regular expression, find the lowest level directory that doesn't contain a wildcard and apply it to the GetDirectories method, attaching the wildcarded string as the search parameter.
Then if your end of string (in this case *.sys) as the search pattern for Directory.GetFiles.
If you wanted to get more complicated and do something like:
C:\Windows\*\Sys*\*.sys
You would use the SearchOptions to set this behaviour:
Directory.GetDirectories(#"C:\Windows", "sys*", SearchOptions.AllDirectories)
This would grab all directories that matched the sys* wildcard in the Windows directory and all directories below it.
If you wanted to get much more complicated than that, then I'm not sure how you would do that... for instance, say you wanted folders that are contained by folders directly inside the Windows directory - I have no idea how you would go about something like that I'm afraid...I don't imagine exporting the entire tree structure to XML and using XPath to do it would be so efficient - the XPath would be fabulously simple for parsing out using wildcards - but converting to XML wouldn't be so efficient...
see the source code of disassembled Microsoft.Build.Shared.FileMatcher class in Microsoft.Build.dll
you can get some idea from the implementation of method GetFiles.
as a client you may use the method as follows
var filelist = FileMatcher.GetFiles(#"c:\alaki",#"c:\alaki\**\bin\*.dll");
Your code looks like exactly how you're supposed to do it.

Categories