Эквивалент команды * Nix 'which' в PowerShell?

Как мне спросить PowerShell, где что-то находится?

Например, «какой блокнот», и он возвращает каталог, из которого запускается notepad.exe, в соответствии с текущими путями.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
448
0
114 895
14
Перейти к ответу Данный вопрос помечен как решенный

Ответы 14

Кажется, это делает то, что вы хотите (я нашел это на 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

Но это не совсем "который", поскольку он работает с любым файлом (типом) и не находит командлеты, функции или псевдонимы.

Jaykul 23.05.2014 19:09

Отметьте это PowerShell Какой.

Приведенный там код предполагает следующее:

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

Я знаю, что прошли годы, но на моем пути было «% systemroot% \ system32 \ ...», и PowerShell не расширяет эту переменную среды и при этом выдает ошибки.

TessellatingHeckler 27.03.2014 09:53

Обычно я просто печатаю:

gcm notepad

или же

gcm note*

gcm - это псевдоним по умолчанию для Get-Command.

В моей системе gcm note * выводит:

[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

Вы получаете каталог и команду, которая соответствует тому, что вы ищете.

это немного беспорядочно, но намного чище, чем пользовательские функции и произвольные разбиения

DevelopingChris 15.09.2008 19:29

Когда я набираю «gcm notepad» в командной строке PowerShell, я получаю только первые два столбца и третий столбец с именем «ModuleName», который пуст. Вы знаете, как заставить его по умолчанию указывать столбец «Определение»?

Piyush Soni 28.11.2016 10:38

@PiyushSoni, вероятно, из-за обновленной версии PowerShell. Вы всегда можете отобразить другие столбцы, выполнив что-то вроде gcm note* | select CommandType, Name, Definition. Однако, если вы запускаете его часто, вам, вероятно, следует обернуть его функцией.

David Mohundro 28.11.2016 21:04
Ответ принят как подходящий

Самым первым псевдонимом, который я сделал после того, как я начал настраивать свой профиль в PowerShell, был «which».

New-Alias which get-command

Чтобы добавить это в свой профиль, введите следующее:

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

`N в начале последней строки гарантирует, что она будет начинаться как новая строка.

Вы можете поместить это в свой скрипт профиля. Подробнее о профилях - msdn.microsoft.com/en-us/library/bb613488(VS.85).aspx

Steven Murawski 15.09.2008 22:45

Мне нравится запускать: Get-Command <command> | Format-Table Path, Name, поэтому я тоже могу получить путь, по которому находится команда.

jrsconfitto 27.11.2012 19:17

Есть ли способ иметь путь все время, не набирая '| Путь к форматной таблице, имя '?

Guillaume 11.01.2013 12:18

В предыдущих версиях Get-Command не предоставлял отсортированный вывод. Теперь это так. Это явно правильный ответ сегодня ;-)

Jaykul 23.05.2014 19:09

Если вы планируете использовать это в сценарии, вам следует передать некоторые дополнительные параметры, чтобы получить такое же поведение, как при прямом вызове в приглашении. Вот пример, если (! (Get-command node -ErrorAction SilentlyContinue)) {'узел не найден' | Write-Error}

Sayed Ibrahim Hashimi 25.10.2014 00:45

Если вы хотите, чтобы поведение в стиле Unix давало вам путь, вам нужно направить вывод get-command в select -expandproperty Path.

Casey 29.07.2015 15:37

Решение @Eld более верное по духу

Jason Newton 14.10.2015 20:49

Как предполагает Джейсон, функция which(), определенная решениеEld, существенно превосходит что-либо, предлагаемую здесь. Если это не эквивалент Unix which, это неправильный ответ.

Cecil Curry 11.06.2016 09:05

Используйте (gcm <command>).definition, чтобы получить только путь (пути). gcm - это псевдоним по умолчанию для Get-Command. Вы также можете использовать подстановочные знаки, например: (gcm win*.exe).definition.

Sachin Joseph 28.02.2017 21:48

В данный момент я изучаю ps, и мне кажется, что помимо того, что он может быть приличным языком сценариев, его довольно глупо использовать в командной строке.

robert 09.03.2018 13:43

На всякий случай, если кому-то еще интересно, если вы заглянете в DLL автоматизации, Source вернет Definition, а Definition вернет Path, так что эти три свойства всегда будут эквивалентны (за исключением некоторых будущих изменений со стороны MS, конечно);

Chad Schouggins 11.04.2018 18:52

Попробуйте выполнить команду where в Windows 2003 или новее (или Windows 2000 / XP, если вы установили Resource Kit).

Кстати, это получило больше ответов на другие вопросы:

Есть ли в Windows аналог «which»?

PowerShell, эквивалентный команде Unix which?

where является псевдонимом командлета Where-Object в Powershell, поэтому ввод where <item> в командной строке Powershell ничего не дает. Таким образом, этот ответ совершенно неверен - как указано в принятом ответе в первом связанном вопросе, чтобы получить DOS where, вам нужно ввести where.exe <item>.

Ian Kemp 01.07.2015 18:09

Вот фактический эквивалент * nix, т.е. он дает вывод в стиле * nix.

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

Просто замените то, что вы ищете.

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

Когда вы добавите его в свой профиль, вы захотите использовать функцию, а не псевдоним, потому что вы не можете использовать псевдонимы с каналами:

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

Теперь, когда вы перезагрузите свой профиль, вы можете сделать это:

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

Я использую альтернативный синтаксис: «(Get-Command notepad) .definition»

Yann 19.12.2013 20:20

@ B00merang У вас отличный синтаксис - определенно более лаконичный - но, к сожалению, даже после удаления канала его нельзя добавить в качестве псевдонима, если вы не укажете имя искомой программы.

petrsnd 26.02.2014 03:29

Это старый пост, но в случае, если кто-то прислал сюда Google (как я), этот ответ работает с большим количеством типов команд Powershell, чем принятый ответ. Например, у меня есть псевдоним okta, который указывает на сценарий Powershell с именем okta.ps1, которого нет на моем $PATH. Использование принятого ответа возвращает имя сценария (okta -> okta.ps1). Это нормально, но он не сообщает мне местонахождение okta.ps1. Однако использование этого ответа дает мне весь путь (C:\Users\blah\etc\scripts\okta.ps1). Итак, +1 от меня.

chris 30.05.2019 21:40

Использовать:

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

Или эту версию, вызывающую исходную команду where.

Эта версия также работает лучше, потому что она не ограничивается файлами 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'
}

Попробуйте этот пример:

(Get-Command notepad.exe).Path

Пожалуйста, добавьте дополнительный код или объяснение, чтобы ОП мог лучше вас понять. Спасибо.

sshashank124 01.04.2014 09:33

Спасибо, что добавили меньше кода, поэтому я могу вспомнить это хоть раз: P

albertjan 03.06.2015 10:30

Это то, что я хотел! Он также работает с gcm: (gcm py.exe).path

Bill Agee 12.07.2016 21:41

Мое предложение для какой функции:

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

PS C:\> which devcon

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

Это лучший ответ, чем принятый. Это позволяет вам добавлять суффиксы постобработки, предложенные выше, чтобы обеспечить лучший результат; псевдоним - нет.

BobHy 12.12.2019 21:19

Быстрое совпадение с Unix which - это

New-Alias which where.exe

Но он возвращает несколько строк, если они существуют, поэтому он становится

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

where.exe where должен сказать вам C:\Windows\System32\where.exe

Chris F Carroll 08.04.2017 22:07

where.exe эквивалентен which -a, поскольку он вернет исполняемые файлы, соответствующие все, а не только первый, который будет выполнен. То есть where.exe notepad дает c:\windows\notepad.exe и c:\windows\system32\notepad.exe. Таким образом, этот нет особенно подходит для формы $(which command). (Другая проблема заключается в том, что если команда не найдена, будет выведено красивое и полезное сообщение об ошибке, которое также не будет хорошо развиваться в $() - это можно исправить с помощью /Q, но не в качестве псевдонима.)

Jeroen Mostert 05.03.2018 19:53

Дело принято. Я отредактировал ответ, но да, это уже не такое изящное решение

Chris F Carroll 07.03.2018 17:50

Обратите внимание, что where, похоже, ищет системную переменную PATH, а не текущую переменную PATH оболочки. См. этот вопрос

Leonardo 22.04.2020 01:12

function which {where.exe $args[0] | select -first 1} сделает его многоразовым. Кроме того, posh кажется более надежным при работе с путями, кавычками и пробелами, поэтому function which {$(gcm $args[0]).source | select -first 1} может быть лучшим выбором.

Nuno André 23.02.2021 14:56

Мне нравится Get-Command | Format-List или короче, используя псевдонимы для двоих и только для powershell.exe:

gcm powershell | fl

Вы можете найти такие псевдонимы:

alias -definition Format-List

Завершение вкладки работает с gcm.

У меня есть эта расширенная функция which в моем профиле PowerShell:

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

Если вам нужна команда, которая принимает ввод из конвейера или как параметр, вы должны попробовать следующее:

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

скопируйте и вставьте команду в свой профиль (notepad $profile).

Примеры:

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

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

Вы можете установить команду which из https://goprogram.co.uk/software/commands вместе со всеми другими командами UNIX.

Другие вопросы по теме