Tương đương với lệnh * Nix 'which' trong PowerShell?


404

Làm cách nào để hỏi PowerShell một cái gì đó ở đâu?

Ví dụ: "notepad" và nó trả về thư mục nơi notepad.exe được chạy từ các đường dẫn hiện tại.

Câu trả lời:


391

Bí danh đầu tiên tôi tạo ra khi tôi bắt đầu tùy chỉnh hồ sơ của mình trong PowerShell là 'cái đó'.

New-Alias which get-command

Để thêm nó vào hồ sơ của bạn, gõ này:

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

`N ở đầu dòng cuối cùng là để đảm bảo nó sẽ bắt đầu như một dòng mới.


1
Bạn có thể đặt nó trong kịch bản hồ sơ của bạn. Thông tin thêm về hồ sơ - msdn.microsoft.com/en-us/l Library / bb613488 (VS85) .aspx
Steven Murawski

62
Tôi thích chạy: Get-Command <command> | Format-Table Path, Namevì vậy tôi có thể nhận được đường dẫn mà lệnh cũng nằm.
jrsconfitto

4
Có cách nào để có đường dẫn mọi lúc mà không cần gõ '| Đường dẫn bảng định dạng, tên '?
Guillaume

10
Nếu bạn muốn hành vi theo kiểu Unix cung cấp cho bạn đường dẫn bạn sẽ cần chuyển đầu ra của lệnh get select -expandproperty Path.
Casey

5
Sử dụng (gcm <command>).definitionđể chỉ nhận (các) đường dẫn. gcmlà bí danh mặc định cho Get-Command. Bạn cũng có thể sử dụng ký tự đại diện, ví dụ : (gcm win*.exe).definition.
Sachin Joseph

165

Đây là một tương đương * nix thực tế, tức là nó cho đầu ra kiểu * nix.

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

Chỉ cần thay thế bằng bất cứ điều gì bạn đang tìm kiếm.

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

Khi bạn thêm nó vào hồ sơ của mình, bạn sẽ muốn sử dụng một chức năng thay vì bí danh vì bạn không thể sử dụng bí danh với các đường ống:

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

Bây giờ, khi bạn tải lại hồ sơ của bạn, bạn có thể làm điều này:

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

22
Tôi sử dụng cú pháp thay thế này: "(not-Command notepad) .def định"
Yann

2
@ B00merang Cú pháp của bạn rất hay - chắc chắn ngắn gọn hơn - nhưng thật không may, ngay cả khi đường ống bị xóa, nó không thể được thêm dưới dạng bí danh trừ khi bạn bao gồm tên của chương trình bạn đang tìm kiếm.
petrsnd

4
Đây là một bài viết cũ, nhưng trong trường hợp bất kỳ ai được gửi đến đây bởi Google (như tôi), câu trả lời này hoạt động với nhiều loại lệnh Powershell hơn câu trả lời được chấp nhận. Ví dụ: tôi có một bí danh có tên oktatrỏ đến tập lệnh Powershell có tên okta.ps1không phải trên tập lệnh của tôi $PATH. Sử dụng câu trả lời được chấp nhận trả về tên tập lệnh ( okta -> okta.ps1). Điều này là ổn nhưng nó không cho tôi biết vị trí của okta.ps1. Tuy nhiên, sử dụng câu trả lời này cho tôi toàn bộ đường dẫn ( C:\Users\blah\etc\scripts\okta.ps1). Vì vậy, +1 từ tôi.
skye --- đội trưởng

88

Tôi thường chỉ gõ:

gcm notepad

hoặc là

gcm note*

gcm là bí danh mặc định cho Get-Command.

Trên hệ thống của tôi, ghi chú gcm * đầu ra:

[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

Bạn nhận được thư mục và lệnh phù hợp với những gì bạn đang tìm kiếm.


nó hơi lộn xộn, nhưng cách sạch hơn các chức năng tùy chỉnh và phân chia tùy ý
DevelopChris

1
Khi tôi gõ "gcm notepad" trong dấu nhắc lệnh powershell, tôi chỉ nhận được hai cột đầu tiên và cột thứ ba có tên 'ModuleName' trống. Bạn có biết cách buộc nó liệt kê cột 'Định nghĩa' theo mặc định không?
Piyush Soni

3
@PiyushSoni có lẽ là do phiên bản cập nhật của PowerShell. Bạn luôn có thể hiển thị các cột khác bằng cách làm một cái gì đó như gcm note* | select CommandType, Name, Definition. Nếu bạn chạy nó thường xuyên, có lẽ bạn nên bọc nó trong một chức năng.
David Mohundro

40

Hãy thử ví dụ này:

(Get-Command notepad.exe).Path

2
Vui lòng thêm nhiều mã hoặc giải thích để OP có thể hiểu bạn hơn. Cảm ơn bạn.
sshashank124

3
Cảm ơn bạn đã thêm ít mã hơn để tôi thực sự có thể nhớ điều này một lần: P
albertjan

1
Đây là những gì tôi muốn! Nó cũng hoạt động với gcm:(gcm py.exe).path
Bill Agee

7

Đề xuất của tôi cho chức năng nào:

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

PS C:\> which devcon

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

Đây là một câu trả lời tốt hơn so với câu trả lời được chấp nhận. Nó cho phép bạn thêm các hậu tố hậu xử lý được đề xuất ở trên để cung cấp đầu ra tốt hơn; một bí danh không.
BobHy

5

Một trận đấu nhanh và bẩn với Unix which

New-Alias which where.exe

Nhưng nó trả về nhiều dòng nếu chúng tồn tại như vậy thì nó trở thành

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

1
where.exe wherenên nói với bạnC:\Windows\System32\where.exe
Chris F Carroll

1
where.exetương đương với which -a, vì nó sẽ trả lại tất cả các tệp thực thi phù hợp, không chỉ là tệp đầu tiên được thực thi. Đó là, where.exe notepadcho c:\windows\notepad.exec:\windows\system32\notepad.exe. Vì vậy, điều này đặc biệt không phù hợp với hình thức $(which command). (Một vấn đề khác là nó sẽ in một thông báo lỗi hữu ích nếu không tìm thấy lệnh, nó cũng sẽ không mở rộng độc đáo $()- có thể được khắc phục /Q, nhưng không phải là bí danh.)
Jeroen Mostert

điểm lấy. Tôi đã chỉnh sửa câu trả lời nhưng vâng, đó không còn là một giải pháp gọn gàng nữa
Chris F Carroll

1
Xin lưu ý rằng wheredường như tìm kiếm biến PATH của hệ thống chứ không phải biến PATH của vỏ hiện tại. Xem câu hỏi này
Leonardo

3

Điều này dường như làm những gì bạn muốn (tôi tìm thấy nó trên 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

Nhưng nó không thực sự "mà" vì nó hoạt động với bất kỳ tệp (loại) nào và không tìm thấy lệnh ghép ngắn, hàm hoặc bí danh
Jaykul

3

Kiểm tra PowerShell này .

Mã được cung cấp ở đó gợi ý điều này:

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

2
Tôi biết đã nhiều năm trôi qua, nhưng đường dẫn của tôi có "% systemroot% \ system32 \ ..." và PowerShell không mở rộng biến môi trường đó và ném lỗi khi thực hiện điều này.
TessellatingHeckler

3

Tôi thích Get-Command | Format-List, hoặc ngắn hơn, sử dụng bí danh cho cả hai và chỉ cho powershell.exe:

gcm powershell | fl

Bạn có thể tìm thấy bí danh như thế này:

alias -definition Format-List

Tab hoàn thành hoạt động với gcm.


2

Thử where lệnh trên Windows 2003 trở lên (hoặc Windows 2000 / XP nếu bạn đã cài đặt Bộ tài nguyên).

BTW, điều này nhận được nhiều câu trả lời hơn trong các câu hỏi khác:

Có tương đương với 'cái nào' trên Windows không?

PowerShell tương đương với whichlệnh Unix ?


4
wherebí danh cho Where-Objectlệnh trong Powershell, vì vậy gõ where <item>vào dấu nhắc Powershell không mang lại kết quả gì. Do đó, câu trả lời này hoàn toàn không chính xác - như đã lưu ý trong câu trả lời được chấp nhận trong câu hỏi được liên kết đầu tiên, để có được DOS where, bạn cần phải gõ where.exe <item>.
Ian Kemp

0

Tôi có whichchức năng nâng cao này trong hồ sơ PowerShell của mình:

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

Sử dụng:

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

Hoặc phiên bản này, gọi lệnh gốc ở đâu.

Phiên bản này cũng hoạt động tốt hơn, vì nó không giới hạn ở các tập tin bat:

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

Nếu bạn muốn một comamnd mà cả hai chấp nhận đầu vào từ đường ống hoặc là paramater, bạn nên thử điều này:

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

sao chép-dán lệnh vào hồ sơ của bạn ( notepad $profile).

Ví dụ:

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

 which clang.exe
C:\Program Files\LLVM\bin\clang.exe
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.