Entspricht dem Befehl * Nix 'which' in PowerShell?


404

Wie frage ich PowerShell, wo sich etwas befindet?

Beispiel: "welcher Notizblock" und es wird das Verzeichnis zurückgegeben, in dem die Datei notepad.exe gemäß den aktuellen Pfaden ausgeführt wird.

Antworten:


391

Der allererste Alias, den ich erstellt habe, als ich anfing, mein Profil in PowerShell anzupassen, war "welcher".

New-Alias which get-command

Geben Sie Folgendes ein, um dies Ihrem Profil hinzuzufügen:

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

Das `n am Anfang der letzten Zeile soll sicherstellen, dass es als neue Zeile beginnt.


1
Sie können es in Ihr Profilskript einfügen. Mehr zu Profilen - msdn.microsoft.com/en-us/library/bb613488(VS.85).aspx
— Steven Murawski

62
Ich laufe gern: Get-Command <command> | Format-Table Path, Namedamit ich den Pfad bekomme, auf dem sich auch der Befehl befindet.
— jrsconfitto

4
Gibt es eine Möglichkeit, den Pfad ständig zu haben, ohne '| eingeben zu müssen? Format-Tabellenpfad, Name '?
— Guillaume

10
Wenn Sie das Unix-Verhalten wünschen, das Ihnen den Pfad gibt, müssen Sie die Ausgabe von get-command an weiterleiten select -expandproperty Path.
— Casey

5
Verwenden Sie (gcm <command>).definitiondiese Option , um nur die Pfade abzurufen. gcmist der Standardalias für Get-Command. Sie können auch Platzhalter verwenden, z (gcm win*.exe).definition.
— Sachin Joseph

165

Hier ist ein tatsächliches * nix-Äquivalent, dh es gibt eine Ausgabe im * nix-Stil.

Get-Command <your command> | Select-Object -ExpandProperty Definition

Ersetzen Sie einfach durch das, was Sie suchen.

PS C:\> Get-Command notepad.exe | Select-Object -ExpandProperty Definition
C:\Windows\system32\notepad.exe

Wenn Sie es Ihrem Profil hinzufügen, möchten Sie eine Funktion anstelle eines Alias ​​verwenden, da Sie keine Aliase mit Pipes verwenden können:

function which($name)
{
    Get-Command $name | Select-Object -ExpandProperty Definition
}

Wenn Sie jetzt Ihr Profil neu laden, können Sie Folgendes tun:

PS C:\> which notepad
C:\Windows\system32\notepad.exe

22
Ich benutze diese alternative Syntax: "(Get-Command Notepad) .definition"
— Yann

2
@ B00merang Ihre Syntax ist großartig - definitiv prägnanter - aber leider kann sie auch ohne entfernte Pipe nicht als Alias ​​hinzugefügt werden, es sei denn, Sie geben den Namen des gesuchten Programms an.
— Petrsnd

4
Dies ist ein alter Beitrag, aber falls jemand von Google hierher geschickt wird (wie ich), funktioniert diese Antwort mit mehr Arten von Powershell-Befehlen als die akzeptierte Antwort. Ich habe beispielsweise einen Alias ​​mit dem Namen okta, der auf ein Powershell-Skript mit dem Namen verweist, okta.ps1das sich nicht in meinem befindet $PATH. Bei Verwendung der akzeptierten Antwort wird der Skriptname ( okta -> okta.ps1) zurückgegeben. Dies ist in Ordnung, aber es sagt mir nicht den Standort von okta.ps1. Die Verwendung dieser Antwort gibt mir jedoch den gesamten Pfad ( C:\Users\blah\etc\scripts\okta.ps1). Also +1 von mir.
— Skye --- Kapitän

88

Normalerweise tippe ich einfach:

gcm notepad

oder

gcm note*

gcm ist der Standardalias für Get-Command.

Auf meinem System gibt gcm note * Folgendes aus:

[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

Sie erhalten das Verzeichnis und den Befehl, die dem entsprechen, wonach Sie suchen.


Es ist ein bisschen chaotisch, aber viel sauberer als benutzerdefinierte Funktionen und willkürliche Aufteilungen
— DevelopingChris

1
Wenn ich "gcm notepad" in meine Powershell-Eingabeaufforderung eingebe, erhalte ich nur die ersten beiden Spalten und eine dritte Spalte namens "ModuleName", die leer ist. Wissen Sie, wie Sie es erzwingen können, die Spalte 'Definition' standardmäßig aufzulisten?
— Piyush Soni

3
@PiyushSoni Das liegt wahrscheinlich an einer aktualisierten Version von PowerShell. Sie können die anderen Spalten jederzeit anzeigen, indem Sie so etwas tun gcm note* | select CommandType, Name, Definition. Wenn Sie es häufig ausführen, sollten Sie es wahrscheinlich in eine Funktion einschließen.
— David Mohundro

40

Versuchen Sie dieses Beispiel:

(Get-Command notepad.exe).Path

2
Bitte fügen Sie mehr Code oder Erklärungen hinzu, damit das OP Sie besser verstehen kann. Vielen Dank.
— sshashank124

3
Vielen Dank, dass Sie weniger Code hinzugefügt haben, damit ich mich einmal daran erinnern kann: P
— Albertjan

1
Das wollte ich! Es funktioniert auch mit gcm:(gcm py.exe).path
— Bill Agee

7

Mein Vorschlag für die Welche Funktion:

function which($cmd) { get-command $cmd | % { $_.Path } }

PS C:\> which devcon

C:\local\code\bin\devcon.exe

Dies ist eine bessere Antwort als die akzeptierte. Sie können die oben vorgeschlagenen Nachbearbeitungssuffixe hinzufügen, um eine bessere Ausgabe zu erzielen. ein Alias ​​nicht.
— BobHy

5

Eine schnelle und schmutzige Übereinstimmung mit Unix whichist

New-Alias which where.exe

Es werden jedoch mehrere Zeilen zurückgegeben, wenn sie vorhanden sind

function which {where.exe command | select -first 1}

1
where.exe wheresollte Ihnen sagenC:\Windows\System32\where.exe
— Chris F Carroll

1
where.exeist gleichbedeutend mit which -a, da alle übereinstimmenden ausführbaren Dateien zurückgegeben werden, nicht nur die erste, die ausgeführt wird. Das heißt, where.exe notepadgibt c:\windows\notepad.exeund c:\windows\system32\notepad.exe. Das ist also besonders für die Form nicht geeignet $(which command). (Ein weiteres Problem ist, dass eine nette, hilfreiche Fehlermeldung ausgegeben wird, wenn der Befehl nicht gefunden wird, die auch nicht gut erweitert wird $()- das kann behoben werden /Q, aber nicht als Alias.)
— Jeroen Mostert

Punkt genommen. Ich habe die Antwort bearbeitet, aber ja, es ist keine so saubere Lösung mehr
— Chris F Carroll

1
Bitte beachten Sie, dass whereanscheinend die System-PATH-Variable und nicht die aktuelle Shell-PATH-Variable durchsucht wird. Siehe diese Frage
— Leonardo

3

Dies scheint zu tun, was Sie wollen (ich fand es auf 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

Aber es ist nicht wirklich "was", da es mit jeder Datei (Typ) funktioniert und keine Cmdlets, Funktionen oder Aliase findet
— Jaykul

3

Überprüfen Sie diese PowerShell Welche .

Der dort bereitgestellte Code schlägt Folgendes vor:

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

2
Ich weiß, dass es Jahre her ist, aber mein Pfad hatte "% systemroot% \ system32 \ ..." und PowerShell erweitert diese Umgebungsvariable nicht und löst dabei Fehler aus.
— TessellatingHeckler

3

Ich mag Get-Command | Format-Listoder kürzer, Aliase für die beiden zu verwenden und nur für powershell.exe:

gcm powershell | fl

Sie können Aliase wie diese finden:

alias -definition Format-List

Die Tab-Vervollständigung funktioniert mit gcm .


2

Probieren Sie die where Befehl unter Windows 2003 oder höher (oder Windows 2000 / XP, wenn Sie ein Resource Kit installiert haben).

Übrigens erhielt dies mehr Antworten in anderen Fragen:

Gibt es ein Äquivalent zu 'which' unter Windows?

PowerShell entspricht dem Unix- whichBefehl?


4
whereAliase für das Where-ObjectCommandlet in Powershell. Wenn Sie also where <item>eine Powershell-Eingabeaufforderung eingeben, erhalten Sie nichts. Diese Antwort ist daher völlig falsch - wie in der akzeptierten Antwort in der ersten verknüpften Frage angegeben, wheremüssen Sie eingeben , um das DOS zu erhalten where.exe <item>.
— Ian Kemp

0

Ich habe diese whicherweiterte Funktion in meinem PowerShell-Profil:

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 }
    }
}

0

Verwenden:

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"
}

Oder diese Version, die den ursprünglichen where-Befehl aufruft.

Diese Version funktioniert auch besser, da sie nicht auf Fledermausdateien beschränkt ist:

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'
}

0

Wenn Sie ein Kommando wünschen, das sowohl Eingaben aus der Pipeline als auch als Parameter akzeptiert, sollten Sie Folgendes versuchen:

function which($name) {
    if ($name) { $input = $name }
    Get-Command $input | Select-Object -ExpandProperty Path
}

Kopieren Sie den Befehl und fügen Sie ihn in Ihr Profil ein ( notepad $profile).

Beispiele:

❯ echo clang.exe | which
C:\Program Files\LLVM\bin\clang.exe

❯ which clang.exe
C:\Program Files\LLVM\bin\clang.exe
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.