3

I'm reading a few relative paths from a file and I'm searching for a function which validates them / brings them into a unified format, like this:

./file1.bin         ->  file1.bin
././file2.bin       ->  file2.bin
file3.bin           ->  file3.bin
folder/f/file4.bin  ->  folder/f/file4.bin
a/b/c/../f.bin      ->  a/b/f.bin
./f/../data.bin     ->  data.bin
./f/../../../d.bin  ->  d.bin

Does such a function exist in C# or would I need to write it myself? While searching I've only found functions which do that conversation relative to a "main path", i. e., converting such a relative path into an absolute one. Or functions that handle / to \ conversation but not trimming the useless "/./" or "/../" blocks.

Florian Bach
  • 919
  • 7
  • 22
  • If you know how to do that "*relative to a main path*", use a main path of your choice and strip it after the conversion. – Amit May 21 '16 at 09:50
  • These functions still don't remove useless ".." and "." parts from the path. Also, then I'd need to take care of people "escaping" into my main path by using too many ".." folders. – Florian Bach May 21 '16 at 09:56
  • 1
    Your problem is basically undefined. `./f/../../../d.bin -> d.bin` doesn't follow any standard rules, so of course you have to do that yourself – Amit May 21 '16 at 10:17
  • http://stackoverflow.com/questions/126242/how-do-i-turn-a-relative-url-into-a-full-url – mohsen May 21 '16 at 10:28
  • 1
    Possible duplicate of [Convert relative path to full URL](http://stackoverflow.com/questions/17421120/convert-relative-path-to-full-url) – mohsen May 21 '16 at 10:29
  • 1
    "doesn't follow standard rules"? Isn't that basically what every archive format also does to stop archives from "escaping" by using multiple ".." folders? restrict the path to the archive root? I'd like to allow ".." to go up one level, but only up to the original root. – Florian Bach May 21 '16 at 10:43

2 Answers2

1

This is as close as I could get using Uri built-in functionality

string file;
string basePath = "c:/someUri/";
Uri baseUri = new Uri(basePath); // fake or real
var list = new List<string>()
{
    "./file1.bin",
    "././file2.bin",
    "file3.bin",
    "folder/f/file4.bin",
    "a/b/c/../f.bin",
    "./f/../data.bin",
    "./f/../../../d.bin"
};
        
foreach (string relative in list)
{
    
    if (Uri.TryCreate(baseUri, relative, out Uri retUri))
    {
        Console.WriteLine("Original: " + relative);
        Console.WriteLine("New     : " + retUri.AbsolutePath);
        
        if (retUri.AbsolutePath.StartsWith(basePath))
            Console.WriteLine("Normal. : " + retUri.AbsolutePath.Substring(basePath.Length));
        else 
            Console.WriteLine("Normal. : " + retUri.AbsolutePath);
                
        file = Path.GetFileName(relative);
        Console.WriteLine("FileName: " + file);
        Console.WriteLine("----------------------");
    }
    else 
        Console.WriteLine(relative + ": NOPE");
}

Result

Original: ./file1.bin
New     : c:/someUri/file1.bin
Normal. : file1.bin
YOUR Res: file1.bin
Success : YES
FileName: file1.bin
----------------------
Original: ././file2.bin
New     : c:/someUri/file2.bin
Normal. : file2.bin
YOUR Res: file2.bin
Success : YES
FileName: file2.bin
----------------------
Original: file3.bin
New     : c:/someUri/file3.bin
Normal. : file3.bin
YOUR Res: file3.bin
Success : YES
FileName: file3.bin
----------------------
Original: folder/f/file4.bin
New     : c:/someUri/folder/f/file4.bin
Normal. : folder/f/file4.bin
YOUR Res: folder/f/file4.binn
Success : YES
FileName: file4.bin
----------------------
Original: a/b/c/../f.bin
New     : c:/someUri/a/b/f.bin
Normal. : a/b/f.bin
YOUR Res: a/b/f.bin
Success : YES
FileName: f.bin
----------------------
Original: ./f/../data.bin
New     : c:/someUri/data.bin
Normal. : data.bin
YOUR Res: data.bin
Success : YES
FileName: data.bin
----------------------
Original: ./f/../../../d.bin
New     : c:/d.bin
Normal. : c:/d.bin
YOUR Res: d.bin
Success : NO !!!!!!
FileName: d.bin

T.S.
  • 18,195
  • 11
  • 58
  • 78
-1

Try this pattern:

Path.GetFullPath((Path.Combine("/", "./f/../data.bin"))).Substring(3);
vimuth
  • 5,064
  • 33
  • 79
  • 116
  • 2
    No explanation how this works. No explanation why this helps. A hesitant, non-assertive, phrasing. No formatting ( https://stackoverflow.com/editing-help ). The [tour] not taken. Hints from [answer] ignored, or never read. – Yunnosch Aug 05 '22 at 21:07