command-line linux - Gibt es in der Windows-Befehlszeile ein Äquivalent zu "which"?




path file (18)

Da ich manchmal Pfadprobleme habe, wo eines meiner eigenen cmd-Skripte von einem anderen Programm (früher auf dem Pfad) versteckt (shadowed) wird, würde ich gerne in der Lage sein, den vollständigen Pfad zu einem Programm in der Windows-Befehlszeile zu finden nur sein Name.

Gibt es ein Äquivalent zum UNIX-Befehl 'which'?

Unter UNIX gibt which command den vollständigen Pfad des angegebenen Befehls aus, um diese Schattenprobleme einfach zu finden und zu reparieren.


Answers

Wenn Sie PowerShell installiert haben (was ich empfehle), können Sie den folgenden Befehl als grobe Entsprechung verwenden (ersetzen Sie Programmname für den Namen der ausführbaren Datei):

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

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


Ich verwende GOW (Gnu unter Windows), eine Light-Version von Cygwin. Sie können es von Github here. erfassen here.

Gow (Gnu On Windows) ist die leichte Alternative zu Cygwin. Es verwendet ein praktisches Windows-Installationsprogramm, das ungefähr 130 äußerst nützliche Open-Source-UNIX-Anwendungen installiert, die als native Win32-Binärdateien kompiliert sind. Es ist so klein wie möglich, etwa 10 MB, im Gegensatz zu Cygwin, die je nach Optionen weit über 100 MB laufen kann. - Über Beschreibung (Brent R. Matzelle)

Screenshot einer Liste von Befehlen, die in GOW enthalten sind.


Weiß nicht, ob das hilft. Gepostet als Antwort, weil ich nicht weiß, wie man Code in Kommentaren formatiert (Hilfe?)

Wenn Sie einen kostenlosen Pascal-Compiler finden können, können Sie dies kompilieren, oder mailen Sie mir, und ich kann versuchen, einen zu extrahieren oder mailen Sie die exe zurück oder poste es irgendwo. Ich poste den Code, schlecht wie er ist, weil es zumindest funktioniert und zeigt den Algorithmus notwendig.

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.

Während neuere Versionen von Windows einen where Befehl haben, können Sie dies auch mit Windows XP tun, indem Sie die Modifizierer für Umgebungsvariablen wie folgt verwenden:

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

Sie benötigen keine zusätzlichen Tools und sind nicht auf PATH beschränkt, da Sie jede Umgebungsvariable (natürlich im Pfadformat), die Sie verwenden möchten, ersetzen können.

Und wenn Sie einen haben wollen, der alle Erweiterungen in PATHEXT handhaben kann (wie Windows selbst), macht dieser den Trick:

@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

Es gibt tatsächlich alle Möglichkeiten zurück, aber Sie können es sehr leicht für bestimmte Suchregeln zwicken.


In Windows CMD, which anruft, where :

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

In Windows-Powershell:

set-alias which where.exe

Holen Sie sich Unexuelle von hier: http://sourceforge.net/projects/unxutils/

Gold auf Windows-Plattformen, setzt alle netten Unix-Utilities auf ein Standard-Windows-DOS. Benutze es seit Jahren.

Es hat ein "was" beinhaltet. Beachten Sie, dass es Groß- und Kleinschreibung ist.

NB: Um es zu installieren, explodieren Sie die Zip irgendwo und fügen Sie ... \ UnxUtils \ usr \ local \ wbin \ zu Ihrer Systempfad-env-Variable hinzu.




Unter PowerShell findet get-command ausführbare Dateien irgendwo in $Env:PATH .

get-command eventvwr

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

Es findet auch Powershell-Cmdlets, Funktionen, Aliase, Dateien mit benutzerdefinierten ausführbaren Erweiterungen über $Env:PATHEXT usw., die für die aktuelle Shell definiert sind (ähnlich dem Bash- type -a foo ), was es zu einem besseren Werkzeug macht als andere Tools wie where.exe , which.exe usw., die diese PowerShell-Befehle nicht kennen.

Sie können schnell einen Alias ​​mit sal which gcm (Kurzform von set-alias which get-command ).


Überrascht, dass niemand Cygwin als Lösung erwähnt hat. Wenn es Ihnen nichts ausmacht, eine Lösung von Drittanbietern zu verwenden, dann ist Cygwin der richtige Weg.

Cygwin bietet Ihnen den Komfort von * nix in der Windows-Umgebung (und Sie können es in Ihrer Windows-Befehlsshell verwenden oder eine * nix-Shell Ihrer Wahl verwenden). Es gibt Ihnen eine ganze Reihe von * nix-Befehlen (wie which ) für Windows, und Sie können dieses Verzeichnis einfach in Ihren PATH .


TCC und TCC / LE von JPSoft sind CMD.EXE-Ersetzungen, die signifikante Funktionalität hinzufügen. Relevant für die OP-Frage, which ein eingebauter Befehl für TCC-Familienbefehlsprozessoren ist.


Ich habe ein ähnliches Werkzeug wie Ned Batchelder erstellt:

Suchen von .dll- und .exe-Dateien in PATH

Während mein Tool in erster Linie für die Suche nach verschiedenen DLL-Versionen verwendet wird, zeigt es mehr Informationen (Datum, Größe, Version), aber es verwendet PATHEXT nicht (ich hoffe, mein Tool bald zu aktualisieren).


Diese Stapeldatei verwendet die CMD-Variablenhandhabung, um den Befehl zu finden, der im Pfad ausgeführt werden würde. Hinweis: Das aktuelle Verzeichnis wird immer vor dem Pfad erstellt. Abhängig davon, welcher API-Aufruf verwendet wird, werden andere Speicherorte vor / nach dem Pfad gesucht.

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

Siehe set /? für Hilfe.


Die GnuWin32 Tools haben, zusammen mit einer ganzen Reihe anderer Unix-Tools.


Die beste Version, die ich unter Windows gefunden habe, ist Joseph Newcomers "whereis" -Dienstprogramm, das von seiner Site aus (mit Quelle) verfügbar ist.

Der Artikel über die Entwicklung von "Where is" ist lesenswert.


Für XP-Benutzer (die keinen where Befehl eingebaut haben), habe ich einen "where like" -Befehl als Rubygem namens whichr

Um es zu installieren, installieren Sie Ruby

dann

gem install whichr

mach es so

c:\>whichr cmd_here


Erweiternd auf die ausgezeichnete Antwort von @ guneys, hier ist ein Tweak, der Benutzer verwenden kann, welche Syntax sie bevorzugen, z

command -x=myfilename.ext --another_switch 

vs

command -x myfilename.ext --another_switch

Das heißt, der Gleichheitsfaktor kann durch Leerzeichen ersetzt werden.

Diese "unscharfe Interpretation" mag Ihnen nicht gefallen, aber wenn Sie Skripte erstellen, die mit anderen Dienstprogrammen austauschbar sind (wie es bei mir der Fall ist, der mit ffmpeg arbeiten muss), ist die Flexibilität nützlich.

STD_IN=0

prefix=""
key=""
value=""
for keyValue in "[email protected]"
do
  case "${prefix}${keyValue}" in
    -i=*|--input_filename=*)  key="-i";     value="${keyValue#*=}";; 
    -ss=*|--seek_from=*)      key="-ss";    value="${keyValue#*=}";;
    -t=*|--play_seconds=*)    key="-t";     value="${keyValue#*=}";;
    -|--stdin)                key="-";      value=1;;
    *)                                      value=$keyValue;;
  esac
  case $key in
    -i) MOVIE=$(resolveMovie "${value}");  prefix=""; key="";;
    -ss) SEEK_FROM="${value}";          prefix=""; key="";;
    -t)  PLAY_SECONDS="${value}";           prefix=""; key="";;
    -)   STD_IN=${value};                   prefix=""; key="";; 
    *)   prefix="${keyValue}=";;
  esac
done




windows command-line path-variables