Вопрос: Есть ли эквивалент «which» в командной строке Windows?


Поскольку у меня иногда возникают проблемы с путями, когда один из моих собственных скриптов cmd скрыт (затенен) другой программой (ранее на пути), я хотел бы иметь возможность найти полный путь к программе в командной строке Windows, учитывая просто его имя.

Есть ли эквивалент команды UNIX «which»?

В UNIX, which commandраспечатывает полный путь данной команды, чтобы легко находить и восстанавливать эти проблемы с затенением.


1870


источник


Ответы:


Windows Server 2003 и более поздние версии (т. Е. Что-либо после 32-разрядной версии Windows XP) предоставляют where.exeпрограмма, которая делает некоторые из whichхотя и соответствует всем типам файлов, а не только исполняемым командам. (Он не соответствует встроенным командам оболочки, например cd.) Он даже примет подстановочные знаки, поэтому where nt*находит все файлы в вашем %PATH%и текущий каталог, имена которого начинаются с nt,

Пытаться where /?для помощи.

Обратите внимание, что Windows PowerShell определяет whereкак псевдоним для Where-Objectкомандлет , поэтому, если вы хотите where.exe, вам нужно ввести полное имя, вместо того чтобы .exeрасширение.


2069



Хотя более поздние версии Windows имеют whereкоманды, вы также можете сделать это с помощью Windows XP с помощью модификаторов переменных среды:

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

Вам не нужны дополнительные инструменты, и это не ограничивается PATHпоскольку вы можете заменить любую переменную среды (в формате пути, конечно), которую вы хотите использовать.


И, если вы хотите использовать все расширения в PATHEXT (как это делает сама ОС Windows), это делает трюк:

@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

Он фактически возвращает все возможности, но вы можете легко настроить его для определенных правил поиска.


255



В PowerShell get-commandнайдет исполняемые файлы в любом месте $Env:PATH,

get-command eventvwr

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

Он также находит командлеты, функции, псевдонимы powershell, файлы с пользовательскими расширениями исполняемых файлов через $Env:PATHEXT, и т. д., определенные для текущей оболочки (довольно похожие на bash's type -a foo), что делает его лучше, чем другие инструменты, такие как where.exe, which.exeи т. д., которые не знают о этих командах PowerShell.

Вы можете быстро настроить псевдоним с помощью sal which gcm(короткая форма set-alias which get-command).


103



В windows powershell:

set-alias which where.exe

39



Если у вас установлен PowerShell (что я рекомендую), вы можете использовать следующую команду в качестве грубого эквивалента (имя подстановки для имени вашего исполняемого файла):

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

Подробнее здесь: http://www.codeassassin.com/blog/PermaLink,guid,fd1967d1-f844-4e29-82e2-f2d6424b4ef9.aspx


37



GnuWin32 инструменты which, а также целый ряд других инструментов Unix.


31



В Windows CMD whichзвонки where:

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

19



Surprised that nobody has mentioned cygwin as a solution yet. If you don't mind using a 3rd-party solution, then cygwin is the way to go.

Cygwin gives you the comfort of *nix in the Windows environment (and you can use it in your Windows command shell, or use a *nix shell of your choice). It gives you a whole host of *nix commands (like which) for Windows, and you can just include that directory in your PATH.


15



In PowerShell, it is gcm, which gives formatted information about other commands. If you want to retrieve only path to executable, use .Source.

For instance: gcm git or (gcm git).Source

Tidbits:


11



Go get unxutils from here: http://sourceforge.net/projects/unxutils/

gold on windows platforms, puts all the nice unix utilities on a standard windows DOS. Been using it for years.

It has a 'which' included. Note that it's case sensitive though.

NB: to install it explode the zip somewhere and add ...\UnxUtils\usr\local\wbin\ to your system path env variable.


8



Dunno if this helps. Posted as answer because I don't know how to format code in comments (help?)

If you can find a free pascal compiler, you can compile this, or email me & I can try to dig one out, or mail back the exe or post it somewhere. I post the code, bad as it is, because at least it works & shows the algorithm necessary.

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

7



Not in stock Windows but it is provided by Services for Unix and there are several simple batch scripts floating around that accomplish the same thing such this this one.


6