Search code examples
powershellpathparent

PowerShell, correct way to detect a root parent folder


For various applications, I need to get the parent folder of some files to use to create other output.

$x = "C:\MyFolder\test.txt"
$parent = Split-Path (Split-Path $x) -Leaf

This works fine, unless I am near the top level.

$x = "C:\test.txt"
$parent = Split-Path (Split-Path $x) -Leaf

This works, and $parent = C:\ but there is no -Leaf as such. What I am left with could be `D:, E:, F:" or maybe even a network location. What in general would be a good way to deal with these cases?

I could do:

if ($parent.length -eq 3) {
    handle-top-level-situation
}

But this feels a little inelegant. Is there a better way to check on a top level when I am checking for a parent folder name in this way?


Solution

  • A solution based on .NET APIs:

    "C:\MyFolder\test.txt", "C:\test.txt" | ForEach-Object { 
    
      $parent = ([IO.FileInfo] $_).Directory.Name
      if ([IO.Path]::IsPathRooted($parent)) {
        "parent dir. is root path: $parent"
      } else {
        "parent dir. name: $parent"
      }
    
    }
    

    Output:

    parent dir. name: MyFolder
    parent dir. is root path: C:\
    

    Alternatively, if you want to rule out files in root directories up front, before even trying to extract the parent directory name, you can use a regex with -notmatch:

    "C:\MyFolder\test.txt", "C:\test.txt" | ForEach-Object {
    
      if ($_ -notmatch '^[a-z]:\\.+?\\.|^\\\\.+?\\.+?\\.') {
        "file is located in a root dir: $_"
      } else {
        "parent dir. name: " + ([IO.FileInfo] $_).Directory.Name
      }
    
    }
    

    Note: The above assumes:

    • regular full paths (no accidental doubling of \ such as in c:\\temp), though the regex could be tweaked to handle them.

    • Windows path separators, i.e. \; to make the regex cross-platform, replace all \\ instances with [\\/].