2

How can I tell if a specified folder is in my PATH using PowerShell?

A function like this would be great:

function FolderIsInPATH($Path_to_directory) {
    # If the directory is in PATH, return true, otherwise false
}
SuperStormer
  • 4,997
  • 5
  • 25
  • 35
Caleb Liu
  • 627
  • 5
  • 18
  • 9
    This question is [being discussed on meta](https://meta.stackoverflow.com/q/419632). – cigien Aug 04 '22 at 16:13
  • 1
    Does https://stackoverflow.com/questions/57493560 help? Or https://stackoverflow.com/questions/5114985 ? – Karl Knechtel Aug 04 '22 at 19:52
  • 10
    @Braiam - Please stop untagging relevant tags. `[path-variables]` is pretty obviously applicable here; there aren't many other cases where you have a `;`-separated list of directories, and matching entries in it is highly relevant for cases like checking whether a directory is already in it before appending to it. Unless/until you get people to agree on meta to a burnination or usage-change for a tag, please don't remove it from questions where it applies. It's not better to have fewer tags. – Peter Cordes Aug 04 '22 at 23:37
  • 2
    @KarlKnechtel, you do a great job at posting Links to Dupes/related Threads, but only posting the bare URL always feels a bit like "Click-Bait"... Maybe more "useful" would be...: [Quoting your Post...]: "*Does [Get PATH evironment variable in PowerShell](/q/57493560) help? Or [Echo %path% on separate lines?](/q/5114985) ?*" // Syntax to use: `[Thread Title](Link to Question, can be shortened like "/q/57493560")`... (No Space between the `[]` and `()` parts...) // + May want to edit the 1st Link/Thread to correct the ugly Typo in the Title btw... (maybe why that Thread didn't get found...!). – chivracq Aug 05 '22 at 05:24
  • 1
    @KarlKnechtel : there's TamperMonkey script [SE Comment Link Helper](https://stackapps.com/q/2378) . I use that in Chromium for link posting. If you're going to post bare URLs, at least post the full link so some of the title words are part of the URL, but titles on the links would be much much better, as chivracq says. – Peter Cordes Aug 05 '22 at 21:21
  • 1
    Related: *[How to check if a directory exists in %PATH%](https://stackoverflow.com/questions/141344/)*. For Windows and restricted to [CMD](https://en.wikipedia.org/wiki/Cmd.exe) (by the tagging), but some answers are in PowerShell anyway. [An answer](https://stackoverflow.com/questions/141344/how-to-check-if-a-directory-exists-in-path/8046515#8046515) addresses the many many complications for a robust and comprehensive solution. – Peter Mortensen Aug 06 '22 at 12:47
  • PowerShell [runs on Linux](https://en.wikipedia.org/wiki/PowerShell#PowerShell_Core_6) as well (since 2018). Does it have an abstraction for the path thingy? – Peter Mortensen Aug 06 '22 at 13:51

4 Answers4

17

Going off this question, you don't need a function for this but can retrieve this with $Env:Path:

$Env:Path -split ";" -contains $directory

The -contains operator is case-insensitive which is a bonus. It could be useful placing this in a function to ensure trailing slashes are trimmed, but that's uncommon:

function inPath($directory) {
    return ($Env:Path -split ';').TrimEnd('\') -contains $directory.TrimEnd('\')
}
Pluto
  • 2,900
  • 27
  • 38
  • Any quoting necessary for a directory with a space in it? – Mark Ransom Aug 04 '22 at 19:40
  • If it's in a variable, no. If manually typing it out, then it needs (single or double) quotes like this: `$Env:Path -split ";" -contains 'C:\Program Files'` – Pluto Aug 04 '22 at 20:23
8

There's a bunch of answers that do a $path.Split(";") or $path -split ";" that will probably be fine for 99.9% of real-world scenarios, but there's a comment on the accepted answer on a similar question here by Joey that says:

Will fail with quoted paths that contain semicolons.

Basically, it's a bit of an edge case, but this is a perfectly valid PATH on Windows:

c:\temp;"c:\my ; path";c:\windows

so here's a hot mess of code to address that...

function Test-IsInPath
{
    param( [string] $Path, [string] $Folder )

    # we're going to treat the path as a csv record, but we
    # need to know how many columns there are so we can create
    # some fake header names. this might give a higher count
    # than the real value if there *are* quoted folders with
    # semicolons in them, but that's not really an issue
    $columnCount = $Path.Length - $Path.Replace(";","").Length

    # generate the list of column names. the actual names
    # don't matter - it's just so ConvertFrom-Csv treats our
    # PATH as a data row instead of a header row
    $headers = 0..$columnCount

    # parse the PATH as a csv record using ";" as a delimiter
    $obj = $path | ConvertFrom-Csv -header $headers -delimiter ";"

    # extract an array of all the values (i.e. folders)
    # in the record we just parsed
    $entries = $obj.psobject.properties.value

    # check if the folder we're looking for is in the list
    return $entries.Contains($Folder)

}

Whether this is a "better" answer than the simple split approach depends on whether you expect to have quoted folders that contain semicolons in your PATH or not :-)...

Example usage:

PS C:\> Test-IsInPath -Path $env:PATH -Folder "c:\temp"
False

PS C:\> Test-IsInPath -Path "c:\temp;`"c:\my ; path`";c:\windows" -Folder "c:\temp"
True

PS C:\> Test-IsInPath -Path "c:\temp;`"c:\my ; path`";c:\windows" -Folder "c:\my ; path"
True

Notes

  • what this still doesn't solve is paths that end (or don't end) with a trailing "\" - e.g. testing for C:\temp when the PATH contains C:\temp\ and vice versa.

  • it also doesn't address any of the other myriad exceptions to path handling listed here: How to check if a directory exists in %PATH%

mclayton
  • 8,025
  • 2
  • 21
  • 26
3

I would go for something like this

function FolderIsInPATH {
    param (
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]$your_searched_folder
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]$Path
    )
    
    $Folders = Get-Childitem -Path $Path -Directory

    foreach ($Folder in $Folders) {
        if ($Folder.Name -eq $your_searched_folder) {
            ##Folder found
        } else {
            ##folder not found
        }
    }
}
Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
LKo.exp
  • 164
  • 7
  • Maybe I forgot to explain that PATH is the environment variable... – Caleb Liu Aug 04 '22 at 13:45
  • Why an explicit loop? Isn't there a built-in function to search in arrays? – Peter Mortensen Aug 05 '22 at 18:06
  • @PeterMortensen: You are right. There is a built in .Net function calles indexof to seach in arrays. But i choose a foreach loop for two main reasons here: 1. The foreach loop is easier to understand for Caleb Liu on how it works and how the script finds the necessary value. 2. I personally think that you are much more flexible with a loop to process this array. But this is only personal preference ;) – LKo.exp Aug 08 '22 at 06:57
2

You can get your PATH using [Environment]::GetEnvironmentVariables()

[Environment]::GetEnvironmentVariables()

Or if you want to get the user environment variables:

[Environment]::GetEnvironmentVariables("User")

Next, get the PATH variable:

$Path = [Environment]::GetEnvironmentVariables().Path # returns the PATH

Then check if the specified folder is in your PATH:

$Path.Contains($Path_to_directory + ";")

The function put together:

function FolderIsInPath($Path_to_directory) {
    return [Environment]::GetEnvironmentVariables("User").Path.Contains($Path_to_directory + ";")
}

However, this function is case-sensitive. You can use String.ToLower() to make it not case-sensitive.

function FolderIsInPath($Path_to_directory) {
    return [Environment]::GetEnvironmentVariables("User").Path.ToLower().Contains($Path_to_directory.ToLower() + ";")
}

Now call your function like this:

FolderIsInPath("C:\\path\\to\\directory")

Note that the path must be absolute.

As pointed out in mclayton's comment, this function won't work for the last path variable. To address this issue, simply add a ; to the end of the path. Your function would now look like this.

function FolderIsInPath($Path_to_directory) {
    return [Environment]::GetEnvironmentVariables("User").Path.ToLower() + ";".Contains($Path_to_directory.ToLower() + ";")
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Caleb Liu
  • 627
  • 5
  • 18
  • 11
    ```$Path.Contains($Path_to_directory + ";")``` won't work if it's the last directory in the list and there's no terminating ```;``` - you might be better doing ```$Path.Split(";").Contains($Path_to_directory)``` instead – mclayton Aug 04 '22 at 15:17