Function Find-Command { <# .SYNOPSIS Used to find a command somewhere on the system. Recursively looks in all paths and under special [Program Files] and [Program Files (x86)] folders if defined. Replacement of `which` command .PARAMETER Filename The filename to look for. #> param ( [Parameter(Mandatory = $true, Position = 0)] $Filename ) $result = (Get-Command $Filename) if ($null -ne $result) { if (![string]::IsNullOrWhiteSpace($result.Path)) { return $result.Path } else { return $result.Source } } if ($Filename.IndexOf('.') -eq -1) { # add a wildcard so it will look for all matching Filename extensions $Filename = "$Filename.*" } # TODO ~ Make this parallel and change the return type $paths = @($env:path -split ';') $paths += $env:ProgramFiles $paths += ${env:ProgramFiles(x86)} $paths = ($paths | Select-Object -Unique) foreach($path in $paths) { if (![string]::IsNullOrWhiteSpace($path)) { $foundItems = Get-ChildItem -Path (Join-Path -Path $path -ChildPath $Filename) -Recurse -ErrorAction Ignore if ($foundItems.Count -eq 1) { return $foundItems.FullName } elseif ($foundItems.Count -gt 1) { Write-Host "Found several results for $Filename" foreach ($foundItem in $foundItems) { Write-Host $foundItem.FullName } Write-Host "" return $foundItems[0] } } } Write-Warning "Could not find a matching file" } Set-Alias -Name which -Value Find-Command