Welcome to MSDN Blogs Sign in | Join | Help

A 90-byte "whereis" program

Sometimes people try too hard.

You can download a C# program to look for a file on your PATH, or you can use a 90-character batch file:

@for %%e in (%PATHEXT%) do @for %%i in (%1%%e) do @if NOT "%%~$PATH:i"=="" echo %%~$PATH:i
Published Thursday, January 20, 2005 7:00 AM by oldnewthing
Filed under:

Comments

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 7:22 AM by David Heffernan
This post would be better if the batch file actually worked. Or even if it was in some way documented.

;-)

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 7:32 AM by Scott
The batch file doesnt work for me, has something do with %PATHTEXT% not being set, it seems.

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 7:44 AM by Nate
It also doesn't work if you specify an extension; 'whereis xcopy' works but 'whereis xcopy.exe' does not.

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 7:46 AM by Mike Dunn
Works fine for me, but remember you have to leave off the extension on %1. So "whereis notepad.exe" won't find anything, use "whereis notepad" instead.

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 7:50 AM by A regular viewer
I know Eric Lippert reads this blog quite often, but a considerable amount of VBScript that lies in Corporate Machines is bloat. FOR/? in CMD.EXE is very much unsung.

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 7:51 AM by mschaef
Ran fine for me. Turned out to be very timely too... I had to use it to figure out which jdk a colleague's machine was running. (so I hit the site, downloaded the script and went with it...)

Thanks, Raymond.

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 7:51 AM by David Heffernan
So it's no use for DLLs since they aren't included in PATHEXT.

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 7:55 AM by JamesW
Does cmd.exe not have an equivalent of 'which'?

james$ which mount_ntfs
/sbin/mount_ntfs

That just finds the executable that would run if you typed in its name - but that's what I'd be looking for in PATH anyway.

@Scott - It's %PATHEXT% (only one 'T') and that ought to be something like:
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH

so Raymond's script will be looking for stuff that Windows will execute too. Works for me (I named it seek.bat):


D:\>seek msdev
c:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin\MSDEV.COM
c:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin\MSDEV.EXE

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 8:12 AM by fleeb
To find 'notepad.exe' (or anything else that specific), you could create the following batch file:

@echo %~$PATH:1

If it cannot find the file, it'll say 'ECHO is on.'. Which, of course, is counter-intuitive. Otherwise, it'll print the path to the file it would execute if you just tried to run it as a command (sort of like the unix 'which' command).

I found myself using this sort of trick a few months ago when I needed a quick-n-easy way to see if the user had installed some file somewhere from within a batch file:

call :mytest SpiffyApp.EXE
if not defined MYEXECUTABLEPATH goto :needexecutable
rem blah blah blah
rem stuff that uses MYEXECUTABLEPATH goes
rem in here.
:needexecutable
echo %0 may only be executed on machines with SpiffyApp installed.
goto :end
:mytest
set MYEXECUTABLEPATH=%~$PATH:1
goto :EOF
:end
endlocal

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 8:17 AM by Vince
Except for not including the cwd, it works great for me... I suppose you could create a temp internal path variable consisting of the current directory plus PATH. That would cover the remaining base, yes?

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 8:27 AM by Pavel A. Kostromitinov
Oh man, once again 4nt.exe (so good in other places) turns to be incompatible with original cmd.exe

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 8:41 AM by Wayne Steele
Vince:
Here's one that looks in your local directory as well:
@setlocal && @set P2=.;%PATH% && @for %%e in (%PATHEXT%) do @for %%i in (%1%%e) do @if NOT "%%~$P2:i"=="" echo %%~$P2:i

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 8:48 AM by Chris Lundie
Thanks Raymond! I'll let the MSN desktop search folks know that they're trying too hard. (Just kidding, or am I?)

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 9:06 AM by Herb
Nearly identical to the one I'd puzzled out a few years back. If you want to eliminate the extension problem (allowing "whereis notepad" or "whereis notepad.exe") you can modify it to be:

@for %%e in (%PATHEXT%) do @for %%i in (%~n1%%e) do @if NOT "%%~$PATH:i"=="" echo %%~$PATH:i

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 9:13 AM by lowercase josh
This won't work on old Win9x machines (that use command.com), since they don't do the fun %~ stuff. Poor, pitiful command.com... :)

There's also been a native win32 port of which in unxutils for a while, although you must specify the extension for that guy.

And if you want it to work when you add an extension, one way is to change (%1%%e) to (%~n1%%e), although that simply ignores it, along with any path you might give it.

fleeb:
@echo:%~$PATH:1
Though this isn't really appropriate to shorten Raymond's version because it'd print too many unsightly blank lines.

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 9:29 AM by romanp
Hmmm... I always use "dir /s" for this. works like a charm

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 9:44 AM by Wayne Steele
The problem with Dir /s is it take forever to look through a bunch of directories you're not even using. Also, if you've got fiver different versions of nmake.exe on your machine, this will tell you which one is being invoked from your current environment.

BTW, the modified script I posted earlier seems to behave weirdly if you run it with everything on one line. This one works better:

@setlocal
@set P2=.;%PATH%
@for %%e in (%PATHEXT%) do @for %%i in (%1%%e) do @if NOT "%%~$P2:i"=="" echo %%~$P2:i

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 9:48 AM by Eric Lippert
I think the point is not that the C# solution is the best way to solve this particular problem, but rather that it is a skeleton upon which can be built more utilities.

How would you modify your 90 character batch file to print out all files on the path with sizes greater than one meg, for example?

90 character batch files are great for simple tasks and throwaway code, but they're hard to maintain, they're hard to debug, and they're hard to extend to any task that benefits from, say, variables that can contain numbers.

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 10:59 AM by ben

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 11:12 AM by Mr. Ed
The real question is, why doesn't the OS come with this command in the first place?

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 11:18 AM by Tim Farley
//4nt.exe...turns to be incompatible

Ah, but in 4NT you can do it this way:

@echo %@search[%1]

Handy translation table to be found here:
http://jpsoft.com/help/batchparms.htm

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 11:38 AM by A
> Ah, but in 4NT you can do it this way:

Or just use the built-in WHICH command.

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 11:41 AM by J. Edward Sanchez
In 4NT, echo %@search[%1] will search for *any* file on the PATH, but the following will find only executable commands (internal, external, aliases, etc.):

which %1

If you feed it a non-executable filename, it will display the assocated executable for the filename.

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 2:35 PM by Pavel Lebedinsky
> The real question is, why doesn't the OS come with this command in the first place?

Where.exe ships with Win2003.

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 3:13 PM by BlackTigerX
>but they're hard to maintain, they're hard to debug

...you are kidding right?

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 3:23 PM by Eric TF Bat
Fleeb - the answer to the "echo is on" problem is:

@echo.%~$PATH:1

I don't know when they put it in (it wasn't in DOS 3), but echo followed by a dot will treat the rest of its argument literally - including leading spaces. So that whereas

echo hello

will print hello at the start of the line, even tho there are many spaces after the "echo" in that line,

echo. hello

(with many spaces after the dot) will work as you expect.

(I hope this comes out in the comment. Blog comment fields with no preview button irritate me, especially when they also do random conversions of their input.)

# re: A 90-byte "whereis" program

Thursday, January 20, 2005 4:15 PM by Keith Moore
Eric -- Maybe something like this:

@if (%_echo%)==() echo off
setlocal ENABLEEXTENSIONS

:Loop
for /F "delims=; tokens=1*" %%i in ("%path%") do (set _cur=%%i&set path=%%j)
for %%i in ("%_cur%\*") do if %%~zi GEQ 1048576 echo %%i
if not "%path%"=="" goto :Loop
goto :EOF

I know, I know -- you make a very valid point. However, the task you mention (finding all files on the path greater than 1M in size) is *possible* with a batch file.

Honestly, I'd prefer Perl for something like this...

# re: A 90-byte "whereis" program

Friday, January 21, 2005 4:06 AM by Paul
That would be so much easier if you just used the Unix 'find' command - for example, to find all files on the path larger than 2048 bytes:

for a in `echo $PATH | sed -e 's/:/ /g'` ; do find $a -type f -size +2k ; done

I'll freely admit there is some line noise in there, but it's an awful lot clearer than the batch file horrors above. :-)

# Jibberish » Blog Archive » ‘which’ for Windows

Friday, January 21, 2005 10:43 AM by TrackBack
Jibberish » Blog Archive » ‘which’ for Windows

# re: A 90-byte "whereis" program

Friday, January 21, 2005 8:17 AM by Mark Hampton
My peeve with all but 4NT's which command is that they ignore the HKLM\software\microsoft\windows\currentversion\App Paths default entry for applications.

# re: A 90-byte "whereis" program

Friday, January 21, 2005 11:08 AM by Ben
Well just wait until we get a real shell w/ Longhorn.

# A minor nitpick

Friday, January 21, 2005 11:42 AM by emmenjay
This works like the Unix "which" program, rather than the "whereis" program.

The "which" program searches your PATH, while "whereis" searches a hard-coded set of common directories.

# re: A 90-byte "whereis" program

Saturday, January 22, 2005 10:23 AM by Muck
Ben, you can have a real shell *right now*. http://www.cygwin.com/

# re: A 90-byte "whereis" program

Sunday, January 23, 2005 11:51 PM by Mike Dunn
4NT is Da Bomb(tm) and it's my command prompt of choice. Little things like list (quick file viewer) select (operate on a bunch of files at once, picking them from a menu), and a better for loop make life so much nicer.

# Bringing cryptic command lines to Windows

Monday, January 24, 2005 10:00 AM by The Old New Thing
Windows Services for Unix is available for free download.

# re: A 90-byte "whereis" program

Monday, January 24, 2005 7:12 AM by Anonymous Coward
Second the http://www.cygwin.com comment...I like to put the bin dir in my path and mix Windows and bash scripting. Doing "dir /s" seems to be way faster than the Cygwin "find" equivalent, but for grovelling through text, grep/awk/perl/python can't be beat.

# re: A 90-byte "whereis" program

Monday, January 24, 2005 5:51 PM by Remmargorp Laer A Ton
If you are on adventurous mood, you can always write a C# code with some interop that sequentially scans the MFT when HDD is found, skipping some less important data (there must be some, how else MFT is so big). You would still need a minifilter to get notifications of changes, as I suspect the filesystemwatcher may not be entirely up for the task - or could it be? Then you just need to write some code that keeps certain percentage of the beginning of the file/path index in memory, should it take too much memory, one can store compressed stream of it and start reading it from the pos that one in the memory ends parallel to using lucene.net to fuzzy match the part of the index on memory to your query.

Or is there a flaw somewhere in this design? The performance and fuzzy matching possibilities should be enough for you average 2 TB workstation like mine. Should do until we get the better one in LongHorn.

# re: A 90-byte "whereis" program

Wednesday, January 26, 2005 12:04 AM by Atif Aziz
This is a cool example indeed, Raymond.

For those looking to include DLLs in the search, this can be done by simply modifying the outermost FOR loop as follows:

@for %%e in (%PATHEXT%;.dll) do ...

Actually, to benefit from precise and already present funtionality in the OS that searches for binaries, one can create a tiny executable that wraps the SearchPath API. This is what I have done in a tool called FindPath that can be found here:

http://www.raboof.com/projects/findpath/findpath.aspx

The SearchPath API, and therefore the FindPath tool, actually look in more locations than just the PATH. See the following MSDN documentation on SearchPath for details:

http://msdn.microsoft.com/library/en-us/fileio/base/searchpath.asp

FindPath also goes one step further and can extract and use assembly manifests together with the Activation Context API to precisely locate the right version of a SxS-enabled DLL. This is useful for libraries like Common Controls 6.0, where doing a simple search along the PATH for COMCTL32.DLL won't yield the right results in Windows XP and 2003.

# Capturing the current directory from a batch file

Friday, January 28, 2005 1:02 PM by The Old New Thing
The % pseudo-variable does the trick.

# Batch building NDoc projects

Saturday, March 05, 2005 9:21 AM by Jelle Druyts

# Which.bat -- "whereis" for old Unix people who hack their Windows something fierce

Wednesday, June 17, 2009 6:07 PM by PITADEV

Which.bat -- "whereis" for old Unix people who hack their Windows something fierce

New Comments to this post are disabled
 
Page view tracker