Pregunta

Como a veces tengo problemas de ruta, donde uno de mis propios scripts cmd está oculto (sombreado) por otro programa (anteriormente en la ruta), me gustaría poder encontrar la ruta completa a un programa en el comando de Windows línea, dado solo su nombre.

¿Existe un equivalente al comando UNIX 'which'?

En UNIX, qué comando imprime la ruta completa del comando dado para encontrar y reparar fácilmente estos problemas de sombreado.

¿Fue útil?

Solución

Windows Server 2003 y posterior (es decir, cualquier cosa después de Windows XP de 32 bits) proporciona el programa where.exe que hace algo de lo que hace which , aunque coincide con todos los tipos de archivos, no solo comandos ejecutables. (No coincide con los comandos de shell integrados como cd ). Incluso aceptará comodines, por lo que donde nt * encuentra todos los archivos en su % PATH% y el directorio actual cuyos nombres comienzan con nt .

Pruebe where /? para obtener ayuda.

Tenga en cuenta que Windows PowerShell define where como un alias para el cmdlet Where-Object , por lo que si desea where.exe , debe escribir el nombre completo en lugar de omitir el .exe extension.

Otros consejos

Mientras que las versiones posteriores de Windows tienen un comando where , también puede hacerlo con Windows XP utilizando los modificadores de variables de entorno, como se indica a continuación:

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

No necesita herramientas adicionales y no se limita a PATH ya que puede sustituir cualquier variable de entorno (en el formato de ruta, por supuesto) que desee utilizar.


Y, si desea una que pueda manejar todas las extensiones en PATHEXT (como lo hace el propio Windows), esta hace el truco:

@echo off
setlocal enableextensions enabledelayedexpansion

:: Needs an argument.

if "x%1"=="x" (
    echo Usage: which ^<progName^>
    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

En realidad, devuelve todas las posibilidades, pero puede ajustarlo con bastante facilidad para reglas de búsqueda específicas.

En PowerShell, Get-Command encontrará archivos ejecutables en cualquier lugar de $ Env: PATH .

Get-Command eventvwr

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

También encuentra cmdlets de PowerShell, funciones, alias, archivos con extensiones ejecutables personalizadas a través de $ Env: PATHEXT , etc., definidos para el shell actual (bastante parecido al tipo de Bash -a foo ): lo que lo convierte en un mejor recurso que otras herramientas como where.exe , which.exe , etc. que desconocen estos comandos de PowerShell.

Encontrar ejecutables usando solo una parte del nombre

gcm *disk*

CommandType     Name                             Version    Source
-----------     ----                             -------    ------
Alias           Disable-PhysicalDiskIndication   2.0.0.0    Storage
Alias           Enable-PhysicalDiskIndication    2.0.0.0    Storage
Function        Add-PhysicalDisk                 2.0.0.0    Storage
Function        Add-VirtualDiskToMaskingSet      2.0.0.0    Storage
Function        Clear-Disk                       2.0.0.0    Storage
Cmdlet          Get-PmemDisk                     1.0.0.0    PersistentMemory
Cmdlet          New-PmemDisk                     1.0.0.0    PersistentMemory
Cmdlet          Remove-PmemDisk                  1.0.0.0    PersistentMemory
Application     diskmgmt.msc                     0.0.0.0    C:\WINDOWS\system32\diskmgmt.msc
Application     diskpart.exe                     10.0.17... C:\WINDOWS\system32\diskpart.exe
Application     diskperf.exe                     10.0.17... C:\WINDOWS\system32\diskperf.exe
Application     diskraid.exe                     10.0.17... C:\WINDOWS\system32\diskraid.exe
...

Encontrar ejecutables personalizados

Para buscar otros ejecutables que no sean de Windows (python, ruby, perl, etc.), las extensiones de archivo para esos ejecutables deben agregarse a la variable de entorno PATHEXT (el valor predeterminado es .COM; .EXE; .BAT; .CMD; .VBS; .VBE; .JS; .JSE; .WSF; .WSH; .MSC; .CPL ) para identificar archivos con estas extensiones en el PATH como ejecutable. Como Get-Command también respeta esta variable, se puede ampliar para enumerar ejecutables personalizados. por ejemplo,

$Env:PATHEXT="$Env:PATHEXT;.dll;.ps1;.psm1;.py"     # temporary assignment, only for this shell's process

gcm user32,kernel32,*WASM*,*http*py

CommandType     Name                        Version    Source
-----------     ----                        -------    ------
ExternalScript  Invoke-WASMProfiler.ps1                C:\WINDOWS\System32\WindowsPowerShell\v1.0\Invoke-WASMProfiler.ps1
Application     http-server.py              0.0.0.0    C:\Users\ME\AppData\Local\Microsoft\WindowsApps\http-server.py
Application     kernel32.dll                10.0.17... C:\WINDOWS\system32\kernel32.dll
Application     user32.dll                  10.0.17... C:\WINDOWS\system32\user32.dll

Puede configurar rápidamente un alias con sal which gcm (forma abreviada de set-alias which get-command ).

Puede encontrar más información y ejemplos en la ayuda en línea para Get-Command .

En Windows PowerShell:

set-alias which where.exe

Si tiene instalado PowerShell (que recomiendo), puede usar el siguiente comando como un equivalente aproximado (nombre de programa sustituto para el nombre de su ejecutable):

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

Más está aquí: ¡Mi Manwich! PowerShell que

Las GnuWin32 las herramientas tienen which , junto con una gran cantidad de otros Unix herramientas.

En Windows CMD que llama a where :

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

Cygwin es una solución. Si no le importa usar una solución de terceros, entonces Cygwin es el camino a seguir.

Cygwin le brinda la comodidad de * nix en el entorno de Windows (y puede usarlo en su shell de comandos de Windows, o usar un shell * nix de su elección). Le ofrece una gran cantidad de comandos * nix (como which ) para Windows, y puede incluir ese directorio en su PATH .

En PowerShell, es gcm , que proporciona información formateada sobre otros comandos. Si desea recuperar solo la ruta al ejecutable, use .Source .

Por ejemplo: gcm git o (gcm git) .Source

Tidbits:

Obtenga unxutils desde aquí: http://sourceforge.net/projects/unxutils/

gold en plataformas Windows, pone todas las buenas utilidades de Unix en un DOS estándar de Windows. Lo he estado usando durante años.

Tiene un 'cual' incluido. Tenga en cuenta que es sensible a mayúsculas y minúsculas.

NB: para instalarlo, explote el zip en algún lugar y agregue ... \ UnxUtils \ usr \ local \ wbin \ a la variable env de la ruta del sistema.

Tengo una función en mi perfil de PowerShell llamada 'which'

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

Así es como se ve la salida:

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:

Si puede encontrar un compilador gratuito de Pascal, puede compilar esto. Al menos funciona y muestra el algoritmo necesario.

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 existence 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 e.g ');
    Writeln('"my_cmd.exe param"');
    Write  ('then invoke Whence with the same extension e.g ');
    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
    { O.K, 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 through 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.

No está disponible en Windows, pero es proporcionado por Servicios para Unix y hay varias secuencias de comandos por lotes simples flotando que logran lo mismo, como este .

La mejor versión de esto que he encontrado en Windows es Joseph Newcomer " whereis " utilidad, que está disponible (con fuente) en su sitio .

El artículo sobre el desarrollo de "whereis" vale la pena leerlo.

Ninguno de los puertos Win32 de Unix que pude encontrar en Internet es satisfactorio, porque todos tienen uno o más de estos defectos:

  • No hay soporte para la variable PATHEXT de Windows. (Que define la lista de extensiones agregadas implícitamente a cada comando antes de escanear la ruta, y en qué orden.) (Uso muchos scripts tcl, y ninguna herramienta disponible públicamente podría encontrarlos).
  • No hay soporte para páginas de códigos cmd.exe, lo que hace que muestren rutas con caracteres no ascii incorrectamente. (Soy muy sensible a eso, con el & # 231; en mi nombre :-))
  • No hay soporte para las distintas reglas de búsqueda en cmd.exe y la línea de comandos de PowerShell. (¡Ninguna herramienta disponible públicamente encontrará scripts .ps1 en una ventana de PowerShell, pero no en una ventana de cmd!)

Así que eventualmente escribí el mío, que admite todo lo anterior correctamente.

Disponible allí: http://jf.larvoire.free.fr/progs/which.exe

Este archivo por lotes utiliza el manejo de variables CMD para encontrar el comando que se ejecutaría en la ruta. Nota: que el directorio actual siempre se realiza antes de la ruta) y dependiendo de qué llamada API se use, se buscan otras ubicaciones antes / después de la ruta.

@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%)

Consulte set /? para obtener ayuda.

Primero puede instalar Git desde Descargando Git , y luego abra Git Bash y escriba:

which app-name

Estoy usando GOW (GNU en Windows), que es una versión ligera de Cygwin. Puede obtenerlo de GitHub aquí .

  

GOW (GNU en Windows) es la alternativa ligera a Cygwin. Usa   un conveniente instalador de Windows que instala aproximadamente 130 extremadamente   útiles aplicaciones de código abierto UNIX compiladas como win32 nativo   binarios Está diseñado para ser lo más pequeño posible, aproximadamente 10 MB, como   a diferencia de Cygwin, que puede ejecutar más de 100 MB dependiendo de   opciones. - Acerca de la descripción (Brent R. Matzelle)

Una captura de pantalla de una lista de comandos incluidos en GOW:

 Ingrese la descripción de la imagen aquí

He creado una herramienta similar a Ned Batchelder:

Buscando archivos .dll y .exe en PATH

Si bien mi herramienta es principalmente para buscar varias versiones de dll, muestra más información (fecha, tamaño, versión) pero no usa PATHEXT (espero actualizar mi herramienta pronto).

Para los usuarios de Windows & nbsp; XP (que no tienen el comando where incorporado), he escrito un " where like " comando como un rubygem llamado whichr .

Para instalarlo, instale Ruby.

Entonces

gem install whichr

Ejecútalo como:

C: > cuál cmd_aquí

TCC y TCC / LE de JPSoft son reemplazos de CMD.EXE que agregan una funcionalidad significativa. Relevante para la pregunta del OP, which es un comando integrado para los procesadores de comandos de la familia TCC.

He usado el módulo which de npm durante bastante tiempo, y funciona muy bien: https://www.npmjs.com/package/which Es una gran alternativa multiplataforma.

Ahora cambié al which que viene con Git. Simplemente agregue a su ruta la ruta / usr / bin de Git, que generalmente se encuentra en C: \ Archivos de programa \ Git \ usr \ bin \ which.exe . El binario which estará en C: \ Program Files \ Git \ usr \ bin \ which.exe . Es más rápido y también funciona como se esperaba.

prueba esto

set a=%~$dir:1
If "%for%"=="" (Echo %1 not found) else (echo %1 found at %a%)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top