Does anyone know how to ask powershell where something is?
For instance "which notepad" and it returns the directory where the notepad.exe is run from according to the current paths.

+2  A: 

This seems to do what you want (i found it on )

Function Find-Path($Path, [switch]$All=$false, [Microsoft.PowerShell.Commands.TestPathType]$type="Any")
## You could  comment out the function stuff and use it as a script instead, with this line:
# param($Path, [switch]$All=$false, [Microsoft.PowerShell.Commands.TestPathType]$type="Any")
   if($(Test-Path $Path -Type $type)) {
      return $path
   } else {
      [string[]]$paths = @($pwd);
      $paths += "$pwd;$env:path".split(";")

      $paths = Join-Path $paths $(Split-Path $Path -leaf) | ? { Test-Path $_ -Type $type }
      if($paths.Length -gt 0) {
         if($All) {
            return $paths;
         } else {
            return $paths[0]
   throw "Couldn't find a matching path of type $type"
Set-Alias find Find-Path
+1 for Jaykul's Find-Path script.
Steven Murawski

Check this: Powershell Which

The code provided there suggests this:

($Env:Path).Split(";") | Get-ChildItem -filter notepad
+9  A: 

I usually just type:

gcm notepad


gcm note*

gcm is the default alias for Get-Command.

On my system, gcm note* outputs:

[27] » gcm note*

CommandType     Name                                                     Definition
-----------     ----                                                     ----------
Application     notepad.exe                                              C:\WINDOWS\notepad.exe
Application     notepad.exe                                              C:\WINDOWS\system32\notepad.exe
Application     Notepad2.exe                                             C:\Utils\Notepad2.exe
Application     Notepad2.ini                                             C:\Utils\Notepad2.ini

You get the directory and the command that matches what you're looking for.

David Mohundro
its a bit messy, but way cleaner than custom functions and arbitrary splits
+14  A: 

The very first alias I made once I started customizing my profile in powershell was 'which'.

New-Alias which get-command

To add this to your profile, type this:

"`nNew-Alias which get-command" | add-content $profile

The `n is to ensure it will start as a new line.

thanks, where do I put this to get it to stick?
You can put it in your profile script. More on profiles -
Steven Murawski
I edited above to address your question ChanChan
+1  A: 

Someone pointed out my blog post about "find" ... but although that's great, it's not really "which" since it works with any file(type) and doesn't find cmdlets, functions or aliases ... the built-in Get-Command should be what you want, but isn't (in v1) because it doesn't sort the output. I wrote a script that sorts Get-Command ... but if you want a strict which-like behavior, you might try modifying it like this:

function which([string]$command) {
begin { $Script:ErrorActionPreference = "SilentlyContinue" }
process {
if(!$_) { $_ = $command }

Microsoft.PowerShell.Core\Get-Command $_ |
   sort {
      if($_.CommandType -match "ExternalScript|Application") {
         1000 + [array]::IndexOf( (Get-Content Env:Path).Split(";"),
                                  [IO.Path]::GetDirectoryName($_.Definition) )
      } else {
   } | Select -first 1 # only return the first item

Hypothetically, you could also modify it to only output the path, instead of the object (which gets formatted as a table), but first of all you'd have to account for functions and cmdlets which don't have paths (eg: the output of which which) and secondly, it's PowerShell ... objects are good :)


One strange point - "gcm alias" gives an error, and yet "alias" entered as a command works (and lists all aliases). I don't understand why this is - I can't find out what type of thing "alias" is: get-help alias finds the alias provider, but that help doesn't mention using "alias" as a command... (I'm using PowerShell V2 CTP3, if it matters)

Paul Moore
The reason for this is that "alias" is an automatic alias for "Get-Alias". Any "Get-*" cmdlet or function (!) automatically gets an alias that is the noun, but only if there is not an existing alias or function with that name. So you can call "Get-FooBar" with "FooBar".