unix like whereis in windows using batch file

Microsoft Windows
Post Reply
User avatar
MigrationUser
Posts: 336
Joined: 2021-Jul-12, 1:37 pm
Contact:

unix like whereis in windows using batch file

Post by MigrationUser »

12 Jun 2012 15:17
chakri292

Hi ,

Copy the below code and save it as whereis.bat file and put it into windir

Code: Select all

@for %%e in (%PATHEXT%) do @for %%i in (%1%%e) do @if NOT "%%~$PATH:i"==""
echo %%~$PATH:i
Usage:
whereis java

This will almost work same as the whereis command in linux.

----------------------------

#2 12 Jun 2012 18:13
Simon Sheppard

A similar example is on the WHERE page (from the OldNewthing blog)
https://ss64.com/nt/where.html

also see
https://ss64.com/nt/syntax-which.html

----------------------------

#3 13 Jun 2012 05:11
dbenham

The WHEREIS.BAT script does not search the current directory, nor does it allow you to explicitly specify a command extension.
It can erroneously list a folder instead of a file.
It is relatively slow.

The WHERE command lists all possible matching files. It properly searches the current directory first and also handles explicit file extensions.
But it would be nice if it had an option to list the file that would execute only. That is easily done by using WHERE in a batch FOR loop and exiting as soon as a file is found. But WHERE is relatively slow, so there is a better solution.

The WHICH.BAT script is very nice in that it properly handles the current directory as well as explicit file extensions. It is also nice that it detects internal commands.
But it can erroneously report a folder instead of a file.
It is also relatively slow.

Below is my version of WHICH.BAT that combines the best features of all of the above, and is very fast and I believe bullet proof.
Some additional improvements:
- Provides an option to store the result in a variable instead of echoing to the screen.
- Sets the ERRORLEVEL to 1 if the file is not found but the command is an internal command. It also outputs an appropriate error message on stderr.
- Sets the ERRORLEVEL to 2 if the file is not found and it is not an internal command. Also outputs an appropriate error message on stderr.

I was forced to do a bunch of delayed expansion toggling because my algorithm needs to expand PATH. But %PATH% will fail if it contains a folder name with an unquoted special character like &. So I need to use !PATH!. But FOR variable expansion will fail if the value contains ! and delayed expansion is enabled.

Code: Select all

::WHICH.BAT  CommandName  [ReturnVar]
::
::  Determines the full path of the file that would execute if
::  CommandName were executed.
::
::  The result is stored in variable ReturnVar, or else it is
::  echoed to stdout if ReturnVar is not specified.
::
::  If no file is found, then an error message is echoed to stderr.
::
::  The ERRORLEVEL is set to one of the following values
::    0 - Success: A matching file was found
::    1 - No file was found and CommandName is an internal command
::    2 - No file was found and CommandName is not an internal command
::    3 - Improper syntax - no CommandName specified
::
@echo off
setlocal disableDelayedExpansion
set "file=%~1"
if not defined file (
  >&2 echo Syntax error: No CommandName specified
  exit /b 3
)
set "noExt="
setlocal enableDelayedExpansion
if "%~x1" neq "" if "!PATHEXT:%~x1=!" neq "!PATHEXT!" set noExt="";
set "modpath=.\;!PATH!"
@for %%E in (%noExt%%PATHEXT%) do @for %%F in ("!file!%%~E") do (
  setlocal disableDelayedExpansion
  if not "%%~$modpath:F"=="" if not exist "%%~$modpath:F\" (
    endlocal & endlocal & endlocal
    if "%~2"=="" (echo %%~$modpath:F) else set "%~2=%%~$modpath:F"
    exit /b 0
  )
  endlocal
)
endlocal
>nul help %~1 && (
  >&2 echo "%~1" is not a valid command
  exit /b 2
)
>&2 echo "%~1" is an internal command

Dave Benham

----------------------------

#4 16 Jun 2012 13:36
Simon Sheppard

^ Thats a pretty damn good script Dave, thanks for posting it.

Edit:
I've replaced the script here with Dave's version
https://ss64.com/nt/syntax-which.html

Last edited by Simon Sheppard (16 Jun 2012 16:26)

----------------------------

#5 15 Jan 2014 20:48
dbenham

Damn! I thought I had a good working version, but then I saw Implement 'which' command in batch script on StackOverflow. My old WhereIs.bat suffers from the same problem - it falsely reports an internal command as external if there happens to exist an exe with the same root name somewhere in the PATH.

I had to completely redesign the test for an internal command, and put that first. It is a bit ugly in that it is dependent on the existence of an empty folder. I create one in the %temp% folder if it does not already exist. I rely on the fact that all internal commands display help if given a single /? option, and an invalid command sets ERRORLEVEL to 9009. I verify that all external commands fail by first verifying the command contains nothing but letters, by clearing the PATH, and by setting my current directory to an empty folder.

Code: Select all

::WHEREIS.BAT  CommandName  [ReturnVar]
::
::  Determines the full path of the file that would execute if
::  CommandName were executed.
::
::  The result is stored in variable ReturnVar, or else it is
::  echoed to stdout if ReturnVar is not specified.
::
::  If no file is found, then an error message is echoed to stderr.
::
::  The ERRORLEVEL is set to one of the following values
::    0 - Success: A matching file was found
::    1 - CommandName is an internal command
::    2 - No file was found and CommandName is not an internal command
::    3 - Improper syntax - no CommandName specified
::
@echo off
setlocal disableDelayedExpansion

set "file=%~1"
setlocal enableDelayedExpansion

if not defined file (
  >&2 echo Syntax error: No CommandName specified
  exit /b 3
)


:: test for internal command
echo(!file!|findstr /i "[^abcdefghijklmnopqrstuvwxyz]" >nul || (
  set "empty=!temp!\emptyFolder"
  md "!empty!" 2>nul
  del /q "!empty!\*" 2>nul >nul
  setlocal
  pushd "!empty!"
  set path=
  (call )
  !file! /? >nul 2>nul
  if not errorlevel 9009 (
    >&2 echo "!file!" is an internal command
    popd
    exit /b 1
  )
  popd
  endlocal
)


:: test for external command
set "noExt="
if "%~x1" neq "" if "!PATHEXT:%~x1=!" neq "!PATHEXT!" set noExt="";
set "modpath=.\;!PATH!"
@for %%E in (%noExt%%PATHEXT%) do @for %%F in ("!file!%%~E") do (
  setlocal disableDelayedExpansion
  if not "%%~$modpath:F"=="" if not exist "%%~$modpath:F\" (
    endlocal & endlocal & endlocal
    if "%~2"=="" (echo %%~$modpath:F) else set "%~2=%%~$modpath:F"
    exit /b 0
  )
  endlocal
)
endlocal


>&2 echo "%~1" is not a valid command
exit /b 2

Dave Benham

Last edited by dbenham (15 Jan 2014 20:52)

----------------------------

#6 24 Feb 2018 00:15
Simon Sheppard

Somehow I missed this update, but better late than never I have now updated the page https://ss64.com/nt/syntax-which.html
Thanks again Dave
Post Reply