How do I 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.
How do I 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.
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 at the start of the last line is to ensure it will start as a new line.
Get-Command <command> | Format-Table Path, Name
so i can get the path where the command sits too. –
Distressed select -expandproperty Path
. –
Chaliapin which()
function defined by Eld's solution is substantially superior to anything on offer here. If it's not the equivalent of Unix which
, it's not the right answer. –
Flemish (gcm <command>).definition
to get the path(s) only. gcm
is the default alias for Get-Command
. You can also use wildcards, eg: (gcm win*.exe).definition
. –
Tigerish Here is an actual *nix equivalent, i.e. it gives *nix-style output.
Get-Command <your command> | Select-Object -ExpandProperty Definition
Just replace with whatever you're looking for.
PS C:\> Get-Command notepad.exe | Select-Object -ExpandProperty Definition
C:\Windows\system32\notepad.exe
When you add it to your profile, you will want to use a function rather than an alias because you can't use aliases with pipes:
function which($name)
{
Get-Command $name | Select-Object -ExpandProperty Definition
}
Now, when you reload your profile you can do this:
PS C:\> which notepad
C:\Windows\system32\notepad.exe
okta
that points to a Powershell script named okta.ps1
that is not on my $PATH
. Using the accepted answer returns the script name (okta -> okta.ps1
). This is OK but it doesn't tell me the location of okta.ps1
. Using this answer, however, gives me the whole path (C:\Users\blah\etc\scripts\okta.ps1
). So +1 from me. –
Abrahamabrahams I usually just type:
gcm notepad
or
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.
gcm note* | select CommandType, Name, Definition
. If you run it often, you should probably wrap it in a function, though. –
Precious Try this example:
(Get-Command notepad.exe).Path
(gcm py.exe).path
–
Clymer My proposition for the Which function:
function which($cmd) { get-command $cmd | % { $_.Path } }
PS C:\> which devcon
C:\local\code\bin\devcon.exe
A quick-and-dirty match to Unix which
is
New-Alias which where.exe
But it returns multiple lines if they exist so then it becomes
function which {where.exe command | select -first 1}
where.exe where
should tell you C:\Windows\System32\where.exe
–
Jesuitism where.exe
is equivalent to which -a
, as it will give back all matching executables, not just the first one to be executed. That is, where.exe notepad
gives c:\windows\notepad.exe
and c:\windows\system32\notepad.exe
. So this is particularly not suitable for the form $(which command)
. (Another problem is that it will print a nice, helpful error message if the command is not found, which will also not expand nicely in $()
-- that can be remedied with /Q
, but not as an alias.) –
Wishywashy where
seems to search the system PATH variable and not the current shell PATH variable. See this question –
Roughspoken function which {where.exe $args[0] | select -first 1}
would make it reusable. Also, posh seems way more reliable in dealing with paths, quotes, and whitespaces, so function which {$(gcm $args[0]).source | select -first 1}
might be a better choice. –
Charlatanism where
is an alias of Where-Object
as gcm where*
will tell you. You have to include the .exe
to restricted it to where.exe
. (FYI sc.exe
is another one.) A frequent suggestion is always use the .exe
as habit to avoid this problem. –
Oriel I like Get-Command | Format-List
, or shorter, using aliases for the two and only for powershell.exe
:
gcm powershell | fl
You can find aliases like this:
alias -definition Format-List
Tab completion works with gcm
.
To have tab list all options at once:
set-psreadlineoption -editmode emacs
This seems to do what you want (I found it on http://huddledmasses.org/powershell-find-path/):
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
Check this PowerShell Which.
The code provided there suggests this:
($Env:Path).Split(";") | Get-ChildItem -filter notepad.exe
Try the where
command on Windows 2003 or later (or Windows 2000/XP if you've installed a Resource Kit).
BTW, this received more answers in other questions:
where
aliases to the Where-Object
commandlet in Powershell, so typing where <item>
in a Powershell prompt yields nothing. This answer is thus completely incorrect - as noted in the accepted answer in the first linked question, to get the DOS where
, you need to type where.exe <item>
. –
Amphigory If you want a comamnd that both accepts input from pipeline or as paramater, you should try this:
function which($name) {
if ($name) { $input = $name }
Get-Command $input | Select-Object -ExpandProperty Path
}
copy-paste the command to your profile (notepad $profile
).
Examples:
❯ echo clang.exe | which
C:\Program Files\LLVM\bin\clang.exe
❯ which clang.exe
C:\Program Files\LLVM\bin\clang.exe
I have this which
advanced function in my PowerShell profile:
function which {
<#
.SYNOPSIS
Identifies the source of a PowerShell command.
.DESCRIPTION
Identifies the source of a PowerShell command. External commands (Applications) are identified by the path to the executable
(which must be in the system PATH); cmdlets and functions are identified as such and the name of the module they are defined in
provided; aliases are expanded and the source of the alias definition is returned.
.INPUTS
No inputs; you cannot pipe data to this function.
.OUTPUTS
.PARAMETER Name
The name of the command to be identified.
.EXAMPLE
PS C:\Users\Smith\Documents> which Get-Command
Get-Command: Cmdlet in module Microsoft.PowerShell.Core
(Identifies type and source of command)
.EXAMPLE
PS C:\Users\Smith\Documents> which notepad
C:\WINDOWS\SYSTEM32\notepad.exe
(Indicates the full path of the executable)
#>
param(
[String]$name
)
$cmd = Get-Command $name
$redirect = $null
switch ($cmd.CommandType) {
"Alias" { "{0}: Alias for ({1})" -f $cmd.Name, (. { which $cmd.Definition } ) }
"Application" { $cmd.Source }
"Cmdlet" { "{0}: {1} {2}" -f $cmd.Name, $cmd.CommandType, (. { if ($cmd.Source.Length) { "in module {0}" -f $cmd.Source} else { "from unspecified source" } } ) }
"Function" { "{0}: {1} {2}" -f $cmd.Name, $cmd.CommandType, (. { if ($cmd.Source.Length) { "in module {0}" -f $cmd.Source} else { "from unspecified source" } } ) }
"Workflow" { "{0}: {1} {2}" -f $cmd.Name, $cmd.CommandType, (. { if ($cmd.Source.Length) { "in module {0}" -f $cmd.Source} else { "from unspecified source" } } ) }
"ExternalScript" { $cmd.Source }
default { $cmd }
}
}
Use:
function Which([string] $cmd) {
$path = (($Env:Path).Split(";") | Select -uniq | Where { $_.Length } | Where { Test-Path $_ } | Get-ChildItem -filter $cmd).FullName
if ($path) { $path.ToString() }
}
# Check if Chocolatey is installed
if (Which('cinst.bat')) {
Write-Host "yes"
} else {
Write-Host "no"
}
Or this version, calling the original where command.
This version also works better, because it is not limited to bat files:
function which([string] $cmd) {
$where = iex $(Join-Path $env:SystemRoot "System32\where.exe $cmd 2>&1")
$first = $($where -split '[\r\n]')
if ($first.getType().BaseType.Name -eq 'Array') {
$first = $first[0]
}
if (Test-Path $first) {
$first
}
}
# Check if Curl is installed
if (which('curl')) {
echo 'yes'
} else {
echo 'no'
}
You can install the which
command from https://goprogram.co.uk/software/commands, along with all of the other UNIX commands.
If you have scoop you can install a direct clone of which:
scoop install which
which notepad
There also always the option of using which. there are actually three ways to access which from Windows powershell, the first (not necessarily the best) wsl -e which command (this requires installation of windows subsystem for Linux and a running distro). B. gnuwin32 which is a port of several gnu binaries in .exe format as standle alone bundled lanunchers option three, install msys2 (cross compiler platform) if you go where it installed in /usr/bin you'll find many many gnu utils that are more up-to-date. most of them work as stand alone exe and can be copied from the bin folder to your home drive somewhere amd added to your PATH.
It's better to wrap where.exe
into the function so that it takes binary as command line argument and put the function into $PROFILE
. Also, to find the directory where the binary is located, it's better to use where.exe
over (Get-Command $binary).Source
method.
Why? Let's consider (Get-Command $binary).Source
where $binary
matches an alias already written in $PROFILE
like, say, New-Alias curl C:\curl-7.81.0-win64-mingw\bin\curl.exe
(because you want to use the curl installed by yourself, not the one in system32). Then the (Get-Command curl).Source
will output nothing. Moreover, even (Get-Command curl.exe).Source
will only output the path to system32:
C:\Windows\System32\curl.exe
when where.exe curl
output looks like this:
C:\Windows\System32\curl.exe
C:\curl-7.81.0-win64-mingw\bin\curl.exe
The same is for default PowerShell aliases, such as where
. The expected output of (Get-Command where).Source
or (Get-Command where).Definition
would be C:\Windows\System32\where.exe
but it just returns nothing instead and "Where-Object"
respectively.
So, the code to add into the $PROFILE
:
function Find-Binary($binary) {
$location = where.exe $binary 2>$null
Write-Output $location
}
New-Alias wi Find-Binary
wi
is short for whereis
Then use it like this:
wi your_binary
or
Find-Binary your_binary
There also always the option of using which. there are actually three ways to access which from Windows powershell
wsl -e which command
This requires installation of windows subsystem for Linux and a running distro.
Next is gnuwin32 which is a port of several gnu binaries in .exe format as standle alone bundled lanunchers
Third, install msys2 (cross compiler platform) if you go where it installed in /usr/bin you'll find many many gnu utils that are more up-to-date. most of them work as stand alone exe and can be copied from the bin folder to your home drive somewhere amd added to your PATH.
© 2022 - 2024 — McMap. All rights reserved.
which
command? – Bootblack