Can’t get to files with multiple consecutive spaces at the end of a FOLDER name

I’m trying to programmaticaly locate a file on a network server where there are multiple directory levels, one of which has two spaces at the end of the name. EG:

\MyServerC$TopLevelAccount [email protected]

Note that the Account level represents many folders using account codes for the folder name, and most of them have the two spaces at the end.

I can’t amend the directory structure as it’s used by other processes outside my control. I will know in advance the path down to and including the Account level, so I need to search the Email level subfolders for a file containing an order number in the file name. I also know the order number.

The problem is that FileInfo, Directory and DirectoryInfo all balk at the two spaces. Whilst Windows has allowed the folders to be created, and an automated third party process can create folders and files below the Account level, nothing I have tried so far has worked because the spaces get stripped out by the c# file and directory classes.

I can’t use:

Directory.GetFiles(PathToTopLevel, "*.pdf")

because there are over 1000 Account level folders, each of which might have 5 or 6 Email level folders with possibly many hundreds of pdf files in each one. I did try it but had to kill it when it was still thinking about it after 5 minutes.

Directory.GetFiles(PathToAccountLevel, "*.pdf")  

This returns the ‘can’t find part of the path’ error.

I also tried:

filePath = Path.Combine(PathToAccountLevel, $"{order_no}.pdf");  
var fi = new FileInfo(filePath);

which also returns ‘can’t find part of the path’.

I’ve done lots of trawling through SO and other forums with no success as they are mainly concerned either with file names or single spaces, but I did find a useful method here which I have tried:

filePath = AddQuotesIfRequired(PathToAccountLevel);  
Directory.GetFiles(filePath, "*.pdf")

Which does indeed add the quotes, but it makes no difference to the outcome.

Also tried (with and without adding quotes):

Directory.GetFiles(@filePath, "*.pdf")  

I’ve tried as many combinations as I can think of using quotes and ‘@’ etc. but absolutely nothing has worked so far. I’ve even hard coded the full path down to the Email level and still no joy.

I’m using C# with VS2019 on Windows 10. The server is running Windows Server 2012 R2 DataCenter. I’ve run the test executable locally on the server and the results are the same.

The really galling aspect of this is that a simple test program written in and using FindFirst/Next works perfectly!

I should also mention that permissions are not an issue, and the files exist.

Any help at all would be great, thanks.

Re the possible duplicate/proposed answer from qaabaam:

Answer 1 for that question is not valid code – the line

DirectoryInfo wantedDir = tempWithoutMac.GetDirectories.Where(c => c.Contains(MacID)).First();

throws an error for GetDirectories being a method and not valid in the context. If you change it to GetDirectories() it then complains that DirectoryInfo does not have a definition for Contains.

Answer 2 using alt 0160 still throws the can’t find part of the path error.

Answer 3 is basically an opinion and doesn’t help at all.

If you can figure out how to get Answer 1 to work I’ll definitely give it a try!

Answer

Leading or trailing spaces in directory names is one of those grey areas in Windows: you can do it, but you probably shouldn’t. The reason for this is simple – the vast majority of the time, a leading or trailing space is a typo, and the Windows APIs around paths have been designed to take this into account, to the point where (as you’ve discovered) they will outright ignore leading or trailing spaces. (For example, in Windows 10, it’s literally impossible to delete a directory with trailing spaces via Windows Explorer!) Since C# is built on top of these APIs, it inherits their “quirks”.

Fortunately there is a way to tell Windows “don’t try to fix this path, it is correct, I know what I’m doing” via the use of DOS device paths. In brief:

  • For local paths, prefix them with the literal \?. In other words, C:foobar would become \?C:foobar.
  • For UNC paths, replace the leading \ with \?UNC. In other words, \serverfoobar would become \?UNCserverfoobar.

In your case, then, all you need to do is change \MyServerC$TopLevelAccount to \?UNCMyServerC$TopLevelAccount and everything should work as you expect.


As an aside, what you are doing is a document search/query operation, which will be incredibly slow as it’s performing I/O, and over the network at that. You’d be far better served in writing a tool to migrate these documents into a proper database, then searching that database for the documents.