Existe um equivalente de ‘which’ na linha de comando do Windows?

Como às vezes tenho problemas de caminho, onde um dos meus próprios scripts cmd é oculto (sombreado) por outro programa (anteriormente no caminho), eu gostaria de poder encontrar o caminho completo para um programa na linha de comando do Windows, dado apenas seu nome.

Existe um equivalente ao comando UNIX ‘which’?

No UNIX, which command imprime o caminho completo do comando fornecido para localizar e reparar facilmente esses problemas de sombreamento.

   

O Windows Server 2003 e versões posteriores (ou seja, qualquer coisa após o Windows XP de 32 bits) fornecem o programa where.exe , que faz parte do which faz, embora corresponda a todos os tipos de arquivos, não apenas a comandos executáveis. (Ele não corresponde a comandos de shell internos como o cd .) Ele aceita até mesmo caracteres curinga, portanto, where nt* localiza todos os arquivos em %PATH% e o diretório atual cujos nomes começam com nt .

Tente where /? para ajuda.

Observe que o Windows PowerShell define where como um alias para o cmdlet Where-Object , portanto, se você desejar where.exe , será necessário digitar o nome completo em vez de omitir a extensão .exe .

Enquanto as versões posteriores do Windows têm um comando where , você também pode fazer isso com o Windows XP usando os modificadores de variables ​​de ambiente, da seguinte maneira:

 c:\> for %i in (cmd.exe) do @echo. %~$PATH:i C:\WINDOWS\system32\cmd.exe c:\> for %i in (python.exe) do @echo. %~$PATH:i C:\Python25\python.exe 

Você não precisa de nenhuma ferramenta extra e não está limitado a PATH já que você pode replace qualquer variável de ambiente (no formato de caminho, é claro) que você deseja usar.


E, se você quiser um que possa lidar com todas as extensões em PATHEXT (como o próprio Windows faz), este faz o truque:

 @echo off setlocal enableextensions enabledelayedexpansion :: Needs an argument. if "x%1"=="x" ( echo Usage: which ^ goto :end ) :: First try the unadorned filenmame. set fullspec= call :find_it %1 :: Then try all adorned filenames in order. set mypathext=!pathext! :loop1 :: Stop if found or out of extensions. if "x!mypathext!"=="x" goto :loop1end :: Get the next extension and try it. for /f "delims=;" %%j in ("!mypathext!") do set myext=%%j call :find_it %1!myext! :: Remove the extension (not overly efficient but it works). :loop2 if not "x!myext!"=="x" ( set myext=!myext:~1! set mypathext=!mypathext:~1! goto :loop2 ) if not "x!mypathext!"=="x" set mypathext=!mypathext:~1! goto :loop1 :loop1end :end endlocal goto :eof :: Function to find and print a file in the path. :find_it for %%i in (%1) do set fullspec=%%~$PATH:i if not "x!fullspec!"=="x" @echo. !fullspec! goto :eof 

Ele realmente retorna todas as possibilidades, mas você pode ajustá-lo facilmente para regras de pesquisa específicas.

Sob o get-command PowerShell get-command você encontrará executáveis ​​em qualquer lugar em $Env:PATH .

 get-command eventvwr CommandType Name Definition ----------- ---- ---------- Application eventvwr.exe c:\windows\system32\eventvwr.exe Application eventvwr.msc c:\windows\system32\eventvwr.msc 

Ele também encontra cmdlets, funções, aliases, arquivos com extensões executáveis ​​customizadas via $Env:PATHEXT , etc definidos para o shell atual (bem parecido com o type -a foo de bash type -a foo ) – tornando-o um melhor access a outras ferramentas como o where.exe , which.exe , etc, que desconhecem esses comandos do PowerShell.

Você pode rapidamente configurar um alias com sal which gcm (forma abreviada de set-alias which get-command ).

No windows powershell:

 set-alias which where.exe 

Se você tiver o PowerShell instalado (o que eu recomendo), você poderá usar o seguinte comando como um equivalente aproximado (substitua programName pelo nome do seu executável):

 ($Env:Path).Split(";") | Get-ChildItem -filter programName* 

Mais aqui: http://www.codeassassin.com/blog/PermaLink,guid,fd1967d1-f844-4e29-82e2-f2d6424b4ef9.aspx

As ferramentas do GnuWin32 têm, juntamente com uma enorme quantidade de outras ferramentas do Unix.

No Windows CMD, which chama where :

 $ where php C:\Program Files\PHP\php.exe 

Surpreso que ninguém tenha mencionado o cygwin como uma solução ainda. Se você não se importa em usar uma solução de terceiros, então o cygwin é o caminho a percorrer.

O Cygwin oferece o conforto do * nix no ambiente Windows (e você pode usá-lo no shell de comando do Windows ou usar um shell * nix de sua escolha). Ele oferece uma grande quantidade de comandos * nix (como o) para o Windows, e você pode simplesmente include esse diretório em seu PATH .

No PowerShell, é gcm , que fornece informações formatadas sobre outros comandos. Se você deseja recuperar apenas o caminho para o executável, use .Source .

Por exemplo: gcm git ou (gcm git).Source

Petiscos:

  • Disponível para o Windows XP.
  • Disponível desde o PowerShell 1.0.
  • gcm é um alias do cmdlet Get-Command .
  • Sem nenhum parâmetro, lista todos os comandos disponíveis oferecidos pelo shell do host.
  • Você pode criar um alias personalizado com Set-Alias which gcm e usá-lo como: (which git).Source .
  • Documentos oficiais: https://technet.microsoft.com/pt-br/library/ee176842.aspx

Vá buscar unxutils a partir daqui: http://sourceforge.net/projects/unxutils/

ouro em plataformas Windows, coloca todos os utilitários unix agradáveis ​​em um DOS padrão do Windows. Estou usando há anos.

Tem um ‘que’ incluído. Note que é sensível a maiúsculas e minúsculas.

Nota: para instalá-lo, exploda o zip em algum lugar e adicione … \ UnxUtils \ usr \ local \ wbin \ à variável env do caminho do sistema.

Eu tenho uma function no meu perfil do PowerShell chamado ‘which’

 function which { get-command $args[0]| format-list } 

Aqui está o que a saída parece:

 PS C:\Users\fez> which python Name : python.exe CommandType : Application Definition : C:\Python27\python.exe Extension : .exe Path : C:\Python27\python.exe FileVersionInfo : File: C:\Python27\python.exe InternalName: OriginalFilename: FileVersion: FileDescription: Product: ProductVersion: Debug: False Patched: False PreRelease: False PrivateBuild: False SpecialBuild: False Language: 

Não sei se isso ajuda. Postado como resposta porque não sei como formatar código nos comentários (ajuda?)

Se você puder encontrar um compilador pascal gratuito, você pode compilar isso, ou mandar um e-mail para mim e eu posso tentar cavar um, ou mandar um e-mail para o exe ou postá-lo em algum lugar. Eu posto o código, por pior que seja, porque pelo menos ele funciona e mostra o algoritmo necessário.

 program Whence (input,output); Uses Dos, my_funk; Const program_version = '1.00'; program_date = '17 March 1994'; VAR path_str : string; command_name : NameStr; command_extension : ExtStr; command_directory : DirStr; search_dir : DirStr; result : DirStr; procedure Check_for (file_name : string); { check existance of the passed parameter. If exists, then state so } { and exit. } begin if Fsearch(file_name,'') <> '' then begin WriteLn('Dos command = ',Fexpand(file_name)); Halt(0); { structured ? whaddayamean structured ? } end; end; function Get_next_dir : DirStr; { Returns the next directory from the path variable, truncating the } { variable every time. Implicit input (but not passed as parameter) } { is, therefore, path_str } var semic_pos : Byte; begin semic_pos := Pos(';',path_str); if (semic_pos = 0) then begin Get_next_dir := ''; Exit; end; result := Copy(Path_str,1,(semic_pos - 1)); { return result } { hmm! although *I* never reference a Root drive (my directory tree) } { is 1/2 way structured), some network logon software which I run } { does (it adds Z:\ to the path). This means that I have to allow } { path entries with & without a terminating backslash. I'll delete } { anysuch here since I always add one in the main program below. } if (Copy(result,(Length(result)),1) = '\') then Delete(result,Length(result),1); path_str := Copy(path_str,(semic_pos + 1), (length(path_str) - semic_pos)); Get_next_dir := result; end; { of function get_next_dir } begin { the following is a kludge which makes the function Get_next_dir easier } { to implement. By appending a semi-colon to the end of the path } { Get_next_dir doesn't need to handle the special case of the last entry } { which normally doesn't have a semic afterwards. It may be a kludge, } { but it's a documented kludge (you might even call it a refinement). } path_str := GetEnv('Path') + ';'; if (paramCount = 0) then begin WriteLn('Whence : V',program_version,' from ',program_date); Writeln; WriteLn('Usage : WHENCE command[.extension]'); WriteLn; WriteLn('Whence is a ''find file''type utility witha difference'); Writeln('There are are already more than enough of those :-)'); Write ('Use Whence when you''re not sure where a command which you '); WriteLn('want to invoke'); WriteLn('actually resides.'); Write ('If you intend to invoke the command with an extension eg '); Writeln('"my_cmd.exe param"'); Write ('then invoke Whence with the same extension eg '); WriteLn('"Whence my_cmd.exe"'); Write ('otherwise a simple "Whence my_cmd" will suffice; Whence will '); Write ('then search the current directory and each directory in the '); Write ('for My_cmd.com, then My_cmd.exe and lastly for my_cmd.bat, '); Write ('just as DOS does'); Halt(0); end; Fsplit(paramStr(1),command_directory,command_name,command_extension); if (command_directory <> '') then begin WriteLn('directory detected *',command_directory,'*'); Halt(0); end; if (command_extension <> '') then begin path_str := Fsearch(paramstr(1),''); { current directory } if (path_str <> '') then WriteLn('Dos command = "',Fexpand(path_str),'"') else begin path_str := Fsearch(paramstr(1),GetEnv('path')); if (path_str <> '') then WriteLn('Dos command = "',Fexpand(path_str),'"') else Writeln('command not found in path.'); end; end else begin { OK, the way it works, DOS looks for a command firstly in the current } { directory, then in each directory in the Path. If no extension is } { given and several commands of the same name exist, then .COM has } { priority over .EXE, has priority over .BAT } Check_for(paramstr(1) + '.com'); { won't return if file is found } Check_for(paramstr(1) + '.exe'); Check_for(paramstr(1) + '.bat'); { not in current directory, search thru path .... } search_dir := Get_next_dir; while (search_dir <> '') do begin Check_for(search_dir + '\' + paramstr(1) + '.com'); Check_for(search_dir + '\' + paramstr(1) + '.exe'); Check_for(search_dir + '\' + paramstr(1) + '.bat'); search_dir := Get_next_dir; end; WriteLn('DOS command not found : ',paramstr(1)); end; end. 

Não em estoque Windows, mas é fornecido pela Services for Unix e existem vários scripts em lote simples flutuando que realizam a mesma coisa, como esta.

A melhor versão disso que eu encontrei no Windows é o utilitário “whereis” de Joseph Newcomer, que está disponível (com fonte) em seu site .

O artigo sobre o desenvolvimento de “whereis” vale a pena ser lido.

Eu criei ferramenta semelhante ao Ned Batchelder:

Procurando arquivos .dll e .exe no PATH

Enquanto minha ferramenta é primordialmente para procurar de várias versões de dll mostra mais informação (data, tamanho, versão) mas não usa PATHEXT (eu espero atualizar minha ferramenta logo).

Nenhum dos portos Win32 do Unix que eu encontrei na Internet são satistazes, porque todos eles têm uma ou mais dessas deficiências:

  • Não há suporte para a variável Windows PATHEXT. (O que define a lista de extensões implicitamente adicionadas a cada comando antes de verificar o caminho e em qual ordem.) (Eu uso vários scripts tcl e não há publicamente disponível qual ferramenta poderia encontrá-los.)
  • Não há suporte para páginas de código cmd.exe, o que faz com que exibam caminhos com caracteres não-ascii incorretamente. (Sou muito sensível a isso, com o ç em meu primeiro nome :-))
  • Não há suporte para as regras de pesquisa distintas no cmd.exe e na linha de comando do PowerShell. (Nenhuma ferramenta disponível publicamente encontrará scripts .ps1 em uma janela do PowerShell, mas não em uma janela cmd!)

Então eu finalmente escrevi o meu próprio que, que suporta todos os itens acima corretamente.

Disponível lá: http://jf.larvoire.free.fr/progs/which.exe

Esse arquivo em lote usa o tratamento de variables ​​CMD para localizar o comando que seria executado no caminho. Nota: que o diretório atual é sempre feito antes do caminho) e dependendo de qual chamada de API é usada, outros locais são procurados antes / depois do caminho.

 @echo off echo. echo PathFind - Finds the first file in in a path echo ======== = ===== === ===== ==== == == = ==== echo. echo Searching for %1 in %path% echo. set a=%~$PATH:1 If "%a%"=="" (Echo %1 not found) else (echo %1 found at %a%) 

Veja o set /? para ajuda.

Você pode primeiro instalar o git em https://git-scm.com/download/win e abrir o git bash e digitar

 which app-name 

TCC e TCC / LE da JPSoft são substituições CMD.EXE que adicionam funcionalidades significativas. Relevante para a pergunta do OP, which é um comando interno para processadores de comando da família TCC.

Para você usuários do XP (que não possuem nenhum comando embutido), eu escrevi um comando “where like” como um rubygem chamado whichr

Para instalá-lo, instale o ruby

então

gem install whichr

corra como

c:\>whichr cmd_here

Eu estou usando GOW (Gnu no Windows), que é uma versão light do cygwin. Você pode grap-lo do github aqui.

O Gow (Gnu On Windows) é a alternativa leve ao Cygwin. Ele usa um conveniente instalador do Windows que instala cerca de 130 aplicativos UNIX de código aberto extremamente úteis compilados como binários nativos do win32. Ele é projetado para ser o menor possível, cerca de 10 MB, ao contrário do Cygwin, que pode funcionar bem acima de 100 MB, dependendo das opções. – Sobre Descrição (Brent R. Matzelle)

Captura de canvas de uma lista de comandos incluídos no GOW.

insira a descrição da imagem aqui

Eu usei o módulo which de npm por um bom tempo, e funciona muito bem: https://www.npmjs.com/package/which É uma ótima alternativa multi-plataforma.

Agora eu mudei para o que vem com o Git. Basta adicionar ao seu caminho o caminho /usr/bin do Git, que geralmente está em C:\Program Files\Git\usr\bin\which.exe . O which binário estará em C:\Program Files\Git\usr\bin\which.exe . É mais rápido e também funciona como esperado.