Setara dengan * Nix perintah 'yang' di PowerShell?


404

Bagaimana cara saya bertanya pada PowerShell di mana ada sesuatu?

Misalnya, "notepad mana" dan mengembalikan direktori tempat notepad.exe dijalankan sesuai dengan jalur saat ini.

Jawaban:


391

Alias ​​pertama yang saya buat setelah saya mulai menyesuaikan profil saya di PowerShell adalah 'yang'.

New-Alias which get-command

Untuk menambahkan ini ke profil Anda, ketikkan ini:

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

`N pada awal baris terakhir adalah untuk memastikannya akan dimulai sebagai baris baru.


1
Anda dapat meletakkannya di skrip profil Anda. Lebih lanjut tentang profil - msdn.microsoft.com/en-us/library/bb613488(VS.85).aspx
Steven Murawski

62
saya suka menjalankan: Get-Command <command> | Format-Table Path, Namejadi saya bisa mendapatkan jalan tempat perintah duduk juga.
jrsconfitto

4
Apakah ada cara untuk memiliki path sepanjang waktu tanpa mengetikkan '| Format-Tabel Path, Nama '?
Guillaume

10
Jika Anda ingin perilaku Unix-style memberi Anda jalan, Anda harus menyalurkan output dari perintah-get select -expandproperty Path.
Casey

5
Gunakan (gcm <command>).definitionuntuk mendapatkan jalur saja. gcmadalah alias default untuk Get-Command. Anda juga dapat menggunakan wildcard, misalnya: (gcm win*.exe).definition.
Sachin Joseph

165

Berikut ini adalah setara * nix aktual, yaitu memberikan * nix-style output.

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

Ganti saja dengan apa pun yang Anda cari.

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

Ketika Anda menambahkannya ke profil Anda, Anda akan ingin menggunakan fungsi daripada alias karena Anda tidak dapat menggunakan alias dengan pipa:

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

Sekarang, ketika Anda memuat ulang profil Anda, Anda dapat melakukan ini:

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

22
Saya menggunakan sintaks alternatif ini: "(Get-Command notepad) .definition"
Yann

2
@ B00merang Sintaks Anda bagus - pasti lebih ringkas - tetapi sayangnya, meskipun pipa dilepas, itu tidak dapat ditambahkan sebagai alias kecuali jika Anda menyertakan nama program yang Anda cari.
petrsnd

4
Ini adalah posting lama, tetapi jika ada orang yang dikirim ke sini oleh Google (seperti saya sebelumnya), jawaban ini berfungsi dengan lebih banyak jenis perintah Powershell daripada jawaban yang diterima. Sebagai contoh, saya memiliki alias bernama oktayang menunjuk ke skrip Powershell bernama okta.ps1yang tidak ada di saya $PATH. Menggunakan jawaban yang diterima mengembalikan nama skrip ( okta -> okta.ps1). Ini baik-baik saja tetapi tidak memberi tahu saya lokasi okta.ps1. Namun, menggunakan jawaban ini memberi saya seluruh jalur ( C:\Users\blah\etc\scripts\okta.ps1). Jadi +1 dari saya.
skye --- kapten

88

Saya biasanya cukup mengetik:

gcm notepad

atau

gcm note*

gcm adalah alias default untuk Get-Command.

Pada sistem saya, gcm note * output:

[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

Anda mendapatkan direktori dan perintah yang cocok dengan apa yang Anda cari.


ini agak berantakan, tapi jauh lebih bersih daripada fungsi kustom dan pemisahan yang sewenang-wenang
DevelopingChris

1
Ketika saya mengetik "gcm notepad" di prompt perintah powershell saya, saya hanya mendapatkan dua kolom pertama, dan kolom ketiga disebut 'ModuleName' yang kosong. Apakah Anda tahu cara memaksanya untuk mencantumkan kolom 'Definisi' secara default?
Piyush Soni

3
@PiyushSoni itu mungkin karena versi PowerShell yang diperbarui. Anda selalu dapat menampilkan kolom lainnya dengan melakukan sesuatu seperti gcm note* | select CommandType, Name, Definition. Jika Anda sering menjalankannya, Anda mungkin harus membungkusnya dalam suatu fungsi.
David Mohundro

40

Coba contoh ini:

(Get-Command notepad.exe).Path

2
Harap tambahkan lebih banyak kode atau penjelasan agar OP dapat memahami Anda dengan lebih baik. Terima kasih.
sshashank124

3
Terima kasih telah menambahkan lebih sedikit kode sehingga saya benar-benar dapat mengingat ini untuk sekali: P
albertjan

1
Inilah yang saya inginkan! Ia bekerja dengan gcm juga:(gcm py.exe).path
Bill Agee

7

Proposisi saya untuk fungsi Mana:

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

PS C:\> which devcon

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

Ini adalah jawaban yang lebih baik daripada yang diterima. Ini memungkinkan Anda untuk menambahkan akhiran postprocessing yang disarankan di atas untuk memberikan hasil yang lebih baik; alias tidak.
BobHy

5

Pertandingan cepat dan kotor untuk Unix whichadalah

New-Alias which where.exe

Tetapi mengembalikan beberapa baris jika ada sehingga menjadi

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

1
where.exe whereharus memberi tahu AndaC:\Windows\System32\where.exe
Chris F Carroll

1
where.exesama dengan which -a, karena akan mengembalikan semua executable yang cocok, bukan hanya yang pertama yang dieksekusi. Artinya, where.exe notepadmemberi c:\windows\notepad.exedan c:\windows\system32\notepad.exe. Jadi ini sangat tidak cocok untuk formulir $(which command). (Masalah lain adalah bahwa ia akan mencetak pesan kesalahan yang bagus dan bermanfaat jika perintah tidak ditemukan, yang juga tidak akan berkembang dengan baik $()- yang dapat diatasi dengan /Q, tetapi tidak sebagai alias.)
Jeroen Mostert

titik diambil. Saya mengedit jawaban tetapi ya itu tidak lagi jadi solusi yang rapi
Chris F Carroll

1
Harap dicatat bahwa wheretampaknya mencari variabel PATH sistem dan bukan variabel PATH shell saat ini. Lihat pertanyaan ini
Leonardo

3

Ini tampaknya melakukan apa yang Anda inginkan (saya menemukannya di 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

Tapi itu tidak benar-benar "yang" karena ini bekerja dengan file (tipe) apa pun dan tidak menemukan cmdlet, fungsi atau alias
Jaykul

3

Periksa PowerShell Yang Ini .

Kode yang disediakan di sana menyarankan ini:

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

2
Saya tahu ini sudah bertahun-tahun, tetapi jalur saya memiliki "% systemroot% \ system32 \ ..." dan PowerShell tidak memperluas variabel lingkungan itu dan melempar kesalahan saat melakukan ini.
TessellatingHeckler

3

Saya suka Get-Command | Format-List, atau lebih pendek, menggunakan alias untuk keduanya dan hanya untuk powershell.exe:

gcm powershell | fl

Anda dapat menemukan alias seperti ini:

alias -definition Format-List

Penyelesaian tab berfungsi dengan gcm.


2

Coba where perintah pada Windows 2003 atau yang lebih baru (atau Windows 2000 / XP jika Anda telah menginstal Resource Kit).

BTW, ini menerima lebih banyak jawaban dalam pertanyaan lain:

Apakah ada yang setara dengan 'yang' pada Windows?

PowerShell setara dengan whichperintah Unix ?


4
wherealias ke Where-Objectcommandlet di Powershell, jadi mengetikkan where <item>prompt Powershell tidak menghasilkan apa-apa. Jawaban ini benar-benar salah - sebagaimana dicatat dalam jawaban yang diterima dalam pertanyaan terkait pertama, untuk mendapatkan DOS where, Anda perlu mengetik where.exe <item>.
Ian Kemp

0

Saya memiliki whichfungsi lanjutan ini di profil PowerShell saya:

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

Menggunakan:

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

Atau versi ini, memanggil perintah asli di mana.

Versi ini juga berfungsi lebih baik, karena tidak terbatas pada file 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

Jika Anda ingin comamnd yang menerima input dari pipa atau sebagai parameter, Anda harus mencoba ini:

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

salin-tempel perintah ke profil Anda ( notepad $profile).

Contoh:

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

 which clang.exe
C:\Program Files\LLVM\bin\clang.exe
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.