I have a file README.TXT
. If I issue the following command:
PS> Get-Item ReadMe.txt
...then it returns "ReadMe.txt". I want to find out the actual name of the file on disk, including case. How do I get it to return "README.TXT"?
I ask because I'm trying to track down a problem with case-insensitive filenames on Windows versus case-sensitive files on a Unix box, and I want to get the actual case used on the Windows box.
More detail: I have a list of files (stored in a .CSPROJ
file) which are in a different case from those stored on disk. I want to be sure that they match. For example: if the .CSPROJ
file says "ReadMe.txt", but the file on disk is "README.TXT", sometimes editing the file in Visual Studio rewrites the file as "ReadMe.txt", which then confuses Perforce, because it's case-sensitive, and the filename no longer has the case it was expecting. I want to write a script that spots the mismatched filenames, so that I can do something about them before it causes a problem.
Here's what I came up with:
The following PowerShell function is based on another developer's elegant solution for C# at https://stackoverflow.com/a/11436327/854680.
Because Get-ChildItem is not used, it is much faster, which makes a difference when calling this function dozens or hundreds of times.
Rather than specifying the exact name, just use a wildcard:
this should return
README.TXT
The bulk of the file system work in PowerShell is done by some .NET classes in the System.IO namespace. If you know the path (like in your example, you've navigated to the file system location where your subject file is located), then you could use something like
Since the base .NET classes are case sensitive, the resulting output of your file names will be case sensitive as well.
For reference, the in the example, you are calling the GetFiles method of the System.IO.DirectoryInfo object that represents the current working directory ($pwd). You can change that to point to the directory containing the file you need to confirm the casing on.
The Name, BaseName, and FullName properties should all reflect the proper casing.
More info on the GetFiles method.
The fastest way I can think of is to replace all the slashes with *\ and then call Get-Item, and to make sure you get no dupes, pick the one that's case-insensitively equal to the one you specified.
Here's my quick and dirty (no validation) approach:
I'll provide an answer in two parts. 1) If you only care about case of the filename and 2) If you care about the case of the full file path.
1. Filename case
The easiest way to get Powershell to give you the correct case of a filename is to have it search for the filename. We can accomplish that by using a RegEx character class (set of valid characters) for the first letter of the filename.
For ReadMe.txt we can search by [R]eadMe.txt. The RegEx character class is intended to be typically used for multiple possible characters, but in this case we simply use one to always obtain a single match:
The above returns the filename with the correct case:
If the filename is being dynamically provided or looked up you can use the following simple RegEx statement to surround the first characters with brackets:
This returns:
Example usage to get the filename with correct case:
The above returns the filename with the correct case:
2. Full File Path case
The basic concept here stays the same as part one. We will have Powershell give us the correct case of all segments of the full file path by having it search for each segment.
Similar to our earlier approach, the easiest way to do that is to surround the first character of each segment by brackets.
If the file name is known, for example:
You can get the correct case for the full path by introducing a RegEx character class (set of valid characters) for the first letter of each segment:
This on my system returns the full path and filename with the correct case:
If the full file path is being dynamically passed in or looked up, you can simply use the following RegEx statement to automatically surround the first character of each segment with brackets:
This returns:
Example usage to get the full file path with correct case:
The above returns the full file path with the correct case: