Home
Name Modified Size InfoDownloads / Week
source 2014-06-05
cmdgo.exe 2014-06-05 25.1 kB
README.txt 2014-06-05 21.2 kB
updates.txt 2014-06-02 8.8 kB
g.bat 2014-05-06 51 Bytes
Totals: 5 Items   55.2 kB 0
G  - A Better Change Directory  command line utility.
(Released as the ChDirAssist project on SourceForge)

--------------------------------------------------------------------
INSTALLATION:
Copy two files to a directory in your execution path:
        g.bat     cmdGO.exe
No other steps are required for installation.
If you have only cmdgo.exe, run it to create g.bat.

--------------------------------------------------------------------
LAST UPDATE JUNE 5, 2014

The "Find New Result" option (/n) now returns the oldest result in history if no actually new result is found.
This essentially eliminates the need for the /nxx options but they will still work if used.
(Function changed on June 2. June 5 is to correct the help text to match.)

See the file UPDATES.TXT for details of all updates.

--------------------------------------------------------------------
USAGE

G is a preprocessor for the Windows "CD" (or "CHDIR") command.

G works like CD for simple cases.  But G will also accept shorthand forms to save you keystrokes, mental strain, and time.  G searches for your target directory, fills in missing information, and generates a complete CD command to take you where you want to go.

=== Basic operation ===

Either "cd abc" or the equivalent "g abc" will change to a subdirectory named "abc" in the current directory.

If the target has a long name like "MySubdirectoryWithaLongname", it can be bothersome to type the whole thing.

Using either G or CD, you may type just enough of the name to identify it uniquely, then use the shell "auto-complete" function by pressing <TAB> to fill in the rest.

Say that "CD my<TAB>" results in: "CD MySubdirectoryWithaLongname".

Then pressing enter will take you there.

But with G you need not use the <TAB> key.  G does its own autocomplete function automatically.  So "g my"  gets you to "MySubdirectoryWithaLongname" immediately.

That's not a big difference, just leaving out the "<TAB>", but it adds up as you go down more levels:

Say that "CD ex<TAB>\ne<TAB>\rec<TAB>\b<TAB>" gets you to "exdir\newcode\recovery\backup".

"G ex\ne\rec\b" does the same thing and feels like less work without those tabs between the parts.

It may be possible to simplify further by using only single initial letters to identify each directory in the path.

Some of those single letters may be ambiguous.  You may have to press <TAB> multiple times to choose the correct subdirectory at each step.

G will encounter the same multiple choices.  But G will look for choices that match all the parts at once, not just the individual parts separately.  This is often enough to find the right place.

If so you could type "g e\n\r\b" instead of "g ex\ne\rec\b" to get to "exdir\newcode\recovery\backup".

There is a shorthand for this "all single initial letter identifiers" form:

"g .enrb" automatically expands to "g e\n\r\b".

For this example I've assumed that the "b" at the end selects the correct terminal directory.  If it does not, you may split it off from the letter string and supply more information.  You might just type the whole name:

"g .enr backup" should  be enough to get you to the right place in almost all cases.

... Which introduces another syntactic variation.  You do not need '\' to separate the directories in a path, spaces will do as well.  You may type "g .enr\backup" or "g .enr backup", whichever you prefer.

=== wildcards ======

G accepts "*" and "?" wildcards.

"?" matches any single character.

"*" matches any number of sequential characters, or none.

So "g *x86" would get you to "Program Files (x86)" on most Windows systems.

Internally, G adds '*' to the end of a name to search for a matching autocomplete name if the name does not match anything exactly as it is typed.

G applies a special interpretation to a single '*' used as a directory name with no other characters.

The '*' in that case means "any number of nested directories of any name".  The number can be 0.

So, to use the earlier "g .enr backup" example, if 'backup' is enough to pick out the right target below you without specifying the intermediate directories, you could use "g * backup" to get to "<...>\exdir\newcode\recovery\backup".

The '*' path wildcard is a powerful tool, but since it initiates a full recursive search it may take a long time to complete if used to search a drive with many directories.

=== extended searches ===

G does an extended search for your target if it cannot be found in your current directory.

This automatic search is limited to your local neighborhood plus all root directories.  Most change directory targets will be found in these places.

If you want a global search you must ask for it explicitly, using an initial '*' wildcard.

To explain the search sequence, suppose that you know about the following directories:

c:\Program Files (*86)
f:\proj1\bin\release
f:\proj1\bin\debug
f:\utility
g:\everquest

And further suppose that you are currently in f:\proj1.

You can type "g bin\release" to get to "Release", and "g bin\debug" to get to "Debug".  This is the same as using CD.

(You could abbreviate these to "g .br"  and "g .bd", but since I am trying to explain the search sequence rather than autocomplete, I'll spell things out.)

G also allows you to type just "g release" or "g debug" to achieve the same results, which would not work with CD, since neither of those targets is in your current working directory.

When G does not find a match starting in your current directory, it will move down one level into your immediate subdirectories (only 'Bin' in this example, but if there are more it will try them each in turn) and repeat the search.  In Bin it finds the target 'release' or 'debug' and changes to it.  Done.

Now assume that you are in "Release" and type "g debug".

There are no subdirectories of "Release" to move down into, (or if there are let's say they do not contain a "debug*"), so this initial search fails, and G looks elsewhere.

The next choice is to move up a level (g ..) to look for a parallel directory.  This puts us in Bin, where it finds Debug and changes to it.  Done.

If the target is still not found, (it was in this example, but suppose that you ask for something else, like "g ut") G will keep moving up to the root of the current drive, repeating the search at each level.

At the root it will find "f:\utility" as a match for "g ut", change to it, and stop. Done.

If instead you ask for "g *86", when G reaches the root of the current drive and still does not find the requested target, it will repeat the search in the root of every other drive on the system, find "c:\Program files (x86)" and change to it.  Done.

Of course, you could have typed "g c:\*86" or even "cd /d c:\pr <TAB><TAB>", but that requires more thought.

I like that I can type "g ut" or "g *86" or "g proj1" or "g ev" from almost anywhere in my systems, and get immediately to the right place.

=== When G does not do an extended search ===

Extended search (local then all drive roots) is the default.

Extended search is turned off when you tell G a specific place to start the search, by:

-  naming a specific drive to search:  eg "g c: xxxx"
-  starting with '.' or '..'

With these you tell G explicitly where to start, so it will not try other starting points.

You may want to use '.' when using '*' to find a target below you.  Otherwise if the target is not found, extended search will deep-search your whole system.

This is not always too bad.  On my laptop with an SSD drive a failed global search is about 12 seconds.  But with a larger system, especially with slow shares, such a search could possibly take minutes to complete.

You may avoid that problem by using "g . * xxxx" instead of "g * xxxx", unless you really do intend to do a global deep search.

=== Searching for files ===

=name is a file name, rather than a directory.  A file "name*" must be found in the directory at the current stage of the search to accept the directory as a match.

Add a '.' if you want only the exact name given.  "=name." will delete the trailing period and suppress the added '*', looking only for exactly "name".

The trailing '.' also works for directory names to suppress the '*' expansion.

I used the =name option the other day to find stat.h.  I was curious about what was in the file, having seen it in some sample code, but I did not see it in the include subdirectories at first.  So I typed "g *=stat.h", and a few seconds later I was in c:\codeblocks\mingw\include\sys, which contains the only copy of that file on my laptop.

Now that I know where it is, I can use "g .cmis" to get there immediately, without a pause for an open search.

The same "g .cmis" command also works on my home system, where CodeBlocks is on a different drive.

I could have done a "dir /s stat.h" from the root of each drive to find stat.h, which is what G does internally. But then since I wanted to look at the file, I would still have to change to the directory as a separate step, or type the whole path or work it out with a series of tabs...  All in all, G made the process easier.

=== Controlling the extend search drive list ===

By default, when doing an extended search, G will try to change to every drive A: to Z: in order.

For many users, this is ok. It is fine for me on my laptop.

But if you want to control the search order or remove some drives from the list set GO_DRIVES=xxxx, where xxxx is just the letters of the drives you want G to use.

I needed to do this on my home system.  I found that doing a DIR /s xxxx on one USB drive attached as a share and plugged into my router took over a minute to complete.

I seldom want to CD to that drive, so taking it out of the search list was an easy choice. I can still "g" to that drive explicitly should the need arise.

Doing a "set go_drives=fgecwv" command from the command line will only affect the current session.

To make the change a permanent default, add GO_DRIVES to the system environment variables.

Details vary with different versions of windows, but on my system I found an "environment variables" window under advanced system settings, which was in system properties from the "computer" tab.  Probably many ways to get there.

=== About spaces in names ===

G treats spaces as delimiters, and does not recognize quotes.

Use // to represent a space in a name.

Program//Files//(x86) == "Program Files (x86)"

Personally, I tend to avoid the problem entirely by skipping over spaces with wildcards.

As in my usual shorthand of *x86 for that directory.


=== About directory names starting with '.' ===

G interprets a string of valid name characters starting with a period as a shorthand code for a series of directories identified by their initial letters.

"g .mydir" is expanded to "g m\y\d\i\r"

However, a directory name with an initial period is valid. So you might mean ".mydir" as a name, not as a shortcut to be expanded.

To use .mydir as an actual directory name, prefix it with "/".

"g /.mydir" looks for the directory ".mydir".

While it will do no harm, there is no need to escape periods inside a name or at the beginning of an =filename.  "myfile.txt","my.favorite.directory", and "=.file" will be processed properly.  Only a leading period in a directory specification has a special meaning requiring the escape code.

=== About history ===

G records the last 100 target directories found in a file GO_HISTORY.TXT in the user's TEMP directory. Duplicates are removed, and the most recent entries are at the top.

G/ will display this list to you in reverse order, so that most recent entries are the last to be displayed.

G/1 to G/99 will go directly to any of the listed targets

G/1 will always go to the previous directory.
So repeatedly typing "g/1" will alternate between two directories.

=== About ambiguous targets ===

If you abbreviate aggressively most targets will be ambiguous, with many possible matches systemwide.

If you enter an ambiguous target, g will go to the first match it finds.

The search order is designed so that this will usually be the target you wanted.  But if it is not, you have a few ways to fix the problem.

If you know where you want to go, the best choice is usually to be more specific about which target you want.

Often another letter or two added to the pattern is enough to pin it down, but if necessary you can specify anything up to a complete path including the drive in which the target is to be found.

Sometimes it may be convenient to specify a file name to pick out the correct target.  G p=myfile might be easier than trying to figure out which of "private directory 312" or "private directory 313" you want, if indeed you want the one containing "myfile".

Otherwise you can use the "new" option, /n, as discussed below.

=== About the "/n" ("new") option. ===

If an ambiguous search lands you in the wrong target directory, you may repeat the search with "/n" added.  G will then find a new target.

Use the up arrow at the command line to redisplay the search command, add "/n" and press enter.

G will repeat the search, rejecting any results already listed in history.

If no new result is found, G will go to the oldest result listed in history.  So repeatedly entering "g <ambiguous search>/n" will cycle through all the matches in your system.

Defaulting to the oldest result on failure is a change from the original /n semantics which eliminates the need for the /nxx function.  But /nxx still works.

/nxx will reject only the most recent xx entries in history, bringing older entries to the top of the history list.

=== About the "trace" option, /t  ===

You might be curious about how G gets to where it winds up.

If you turn on tracing with /t, G will print out the major steps it takes in attempting to find your target.

This will also show you how G interpreted your input, listing each of the search terms G is using.

This can for example let you see where an unexpectedly long search pauses, perhaps highlighting a drive that is slow to search and should be removed from the default search list.

There is also a more detailed trace available with /t2.  This is mostly for debugging, should G misbehave, but there is no harm in trying it.

=== About G0,G1,G2 ===

These are environment variables set by G each time it is run, containing the last 3 history entries.

G does not use them, they are for your convenience.

You can display them with "set g", and may use them for various purposes.

For instance "copy %g1%\*.txt"  will copy all the .txt files from the last directory you were in to the current dirctory.

=== Here is a copy of the help text that is printed if you type "g/?" (or "g/h")
:
: G === (go) A Better Change Directory program
:
: G [drive:][\][part1] [part2] ... [partN] [/options]
:
: G searches for a path matching all parts given.
:
: Each part can be either a directory name or =filename to specify
: a file to be found in the directory at this point in the search.
:
: If no drive or initial '\' is given, G looks in the current directory.
: Then in subdirectories just below it.
: Then in successively higher levels to the current root directory.
: Then in the root directories of other drives.
: Change the drives to be auto-searched by using 'set go_drives=dddd'
:
: If a drive is specified, look only in the root of that drive.
:
: An initial '\' starts in the current root then looks at other drives.
:
: Wildcards '*' and '?' are allowed, and if a name as entered
: cannot be found, an '*' will be automatically appended.
: Add '.' to the end of a name to suppress the automatic '*'.
:
: Parts may be separated by spaces or '\'
: Parts may not contain spaces.  Use // to represent a space.
:
: A single '*' matches 0 or more nested directories of any name.
: Use '**' to require specifically one subdirectory.
:
: .abcde is expanded to a\b\c\d\e  Use /.abcde for name '.abcde'
:
: '/t' turns on tracing, to display the steps in the search
:
: History is stored in %temp%\GO_HISTORY.TXT
: '/'   means list all directories in history
: '/1' to '/99'  means go a directory in history,
:  where /1=previous directory, /2=the one before, etc.
:
: '/n' appended to a search means find a new matching result,
:      a directory not recently visited.
:
: Environment variables %G0% %G1% %G2% are set to /0, /1, and /2.
: Use them for example to copy files between recent directories.
:
: Examples:
:
: TYPED               RESULT (varies from system to system)
: g ut                cd /d f:\utility
: g *x86              cd /d c:\program files (x86)
: g .cmi              cd /d f:\CodeBlocks\MingW\include
: g c *=stat.h        cd /d f:\CodeBlocks\MingW\include\sys
:

---------------------------------------------
BACKGROUND

I wrote this to recreate the function of an old G.COM program from sometime in the 80's.  Such programs no longer work in 64-bit Windows, and in any case the old G did not understand long names so it was not particularly useful even in XP where it would still run.

An EXE program runs in a separate process and cannot directly change the current directory for the cmd shell.  So G is a batch file that calls gocmd.exe.  GOCMD writes the commands to change the directory and set environment variables to another temporary batch file. G.bat chains to that when it regains control to effect the changes in the shell environment. This all happens in a blink so that you don't actually see the chaining.

This was a casual effort for my own use.  But it turned out nicely, and I find it useful so I thought I would share it with others.

---------------------------------------------
Comparison to WCD -- Wherever Change Directory

There are other "change directory" utilities available.  Of the ones I found, WCD is perhaps the most elaborate.

All these alternatives seem to be inspired by the old "Norton Change Directory" utility, and they all build and search an index of the file system rather than searching the file system itself.

G searches the the file system directly, with no index.

Using an index can be faster, but it also imposes some limitations.  G can find files, WCD cannot.  G can find the directory you just created, WCD cannot until you have it re-scan the file system.

The speed difference is not so dramatic as you might expect.  For most directory changes that you want to make, G will find the target and change directories with no visible delay, so it doesn't usually matter.

WCD is a bigger project.  It supports many languages/locales/character sets, and can run on many platforms.  Just looking at all the options is overwhelming.

G is tiny and coded narrowly for my sort of environment: a windows command shell in English.

But even though WCD is in some ways a more powerful "directory finder", it does not do what G does.

We have different goals.  I want a typing aid, an assistant that will make it easier to navigate my filesystem  without distracting me.  I want something that I will use routinely instead of the Windows CD command for every casual directory change.

WCD seems to be more useful when your focus is actually on finding a directory.  It is not particularly helpful for the routine changes among familiar targets that are incidental to your normal workflow.

WCD has no sense of locality. If you give it an ambiguous target it has no basis for picking a "most likely" choice.  It will clear the screen and pop up a menu making you choose among all of the possible matches system-wide.

The choice is quick and easy: just press a single letter, if the choice is among the first 26 listed.

But I find it distracting.  My screen is cleared of whatever I was doing, and there is a lot of text to read.

WCD has given me ideas for useful extensions to my own approach.

But for my purposes G is better.

And I still have not found an equivalent function elsewhere on the web.

------------------------------------------------------------------
LICENSING

I don't know much about such stuff.  I wrote this for my own use, but would be pleased if others want to use it also.  I don't mind if others find a use for the actual code as well.

Since some sort of licensing statement seems to be a normal part of projects here, consider this project, including both source and binaries, to be covered by the GNU public license:

http://www.gnu.org/licenses/gpl.html

--------------------------------------------------------------------
SUPPORT

This was a personal coding effort.  It works for me.  But I make no guarantees of any kind, nor do I promise further support.

That said, if you find a problem or want something changed or added or just want to comment, notes to the discussion board that Sourceforge set up automatically would be very welcome.

Bill Modlin

--------------------------------------------------------------------
Source: README.txt, updated 2014-06-05