radrow
radrow

Reputation: 7139

What to append to a path to make it point to the file system root?

I have some path, let's say C:\Windows\System32\WindowsPowerShell\. I would like to find such a string, that when appended (from the right side), will make this path point to C:\.

Well, that is easy if the path is set; I could just make it C:\Windows\System32\WindowsPowerShell\..\..\..\.

What I am looking for however, is a fixed string that would work every time, no matter how the initial path looks (and especially how long it is). Does Windows offer some tricks to help this? If it is impossible to achieve, then it's a valid answer.

Bonus points: can I refer to a different hard drive this way?

Upvotes: 0

Views: 168

Answers (3)

lit
lit

Reputation: 16236

The root is available in the FileInfo object.

PS C:\src\t> (Get-ChildItem -Path 'C:\Windows\System32\WindowsPowerShell\').PSDrive.Root
C:\

Upvotes: 0

mklement0
mklement0

Reputation: 437823

A fixed string is not an option, but it's easy to dynamically construct one for a given path of arbitrary length.

Taking advantage of the fact that *, when applied to string on the LHS, replicates that string a given number of times (e.g., 'x' * 3 yields xxx):

# Sample input path.
$path = 'C:\Windows\System32\WindowsPowerShell'

# Concatenate as many '..\' instances as there are components in the path.
$relativePathToRoot = '..\' * $path.Split('\').Count
$absolutePathToRoot = Join-Path $path $relativePathToRoot

# Sample output
[pscustomobject] @{
  RelativePathToRoot = $relativePathToRoot
  AbsolutePathToRoot = $absolutePathToRoot
}

Note: On Unix, use '../' * $path.Split('/').Count; for a cross-platform solution, use "..$([IO.Path]::DirectorySeparatorChar)" * $path.Split([IO.Path]::DirectorySeparatorChar).Count; for a solution that can handle either separator on either platform (and uses / in the result), use '../' * ($path -split '[\\/]').Count

Output:

RelativePathToRoot AbsolutePathToRoot
------------------ ------------------
..\..\..\..\       C:\Windows\System32\WindowsPowerShell..\..\..\..\

Upvotes: 1

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174485

Use Convert-Path to resolve/consolidate the given path, then keep adding .. until you reach the root of the volume:

# Grab current location from `$pwd` automatic variable
$path = "$pwd"

# Calculate path root 
$root = [System.IO.Path]::GetPathRoot($path)

while((Convert-Path $path) -ne $root){
  # We haven't reached the root yet, keep backing up
  $path = Join-Path $path '..'
}

$path now contains C:\Current\Relative\Path\..\..\.. and you can now do:

& path\to\myBinary.exe (Join-Path $path.Replace("$pwd","").TrimStart('\') targetfile.ext)

$path.Replace("$pwd", "") gives us just \..\..\.., and TrimStart('\') removes the leading path separator so as to make the path relative, so the resulting string passed to the binary will be ..\..\..\targetfile.ext

Upvotes: 2

Related Questions