setdir - Extended replacement for the cd command
setdir [-?,-help] [-debug]
[-histsize=num] [-netsearch=bool] [-automap=bool] [-report=bool]
[-verbose=bool] [-state]
[-list pattern] [-purge pattern] [-clean]
[:num] [path]
setdir offers a much improved replacement for the cd command. It keeps track of directories you
visit and allows you to jump from directory to directory quickly and easily. It also connects you to
network drives automatically and removes the need to change drives explicitly. This differs from
other approaches which use hard-coded aliases or scripts to hop to specific directories, since
setdir dynamically keeps track of your movements from directory to directory, and learns your
environment without any maintenance needed on your part.
setdir works by maintaining a list of places you've been, most recent first. Though old
directories eventually fall off the bottom of the list, the size of the history is easily
configurable. (This size is 200 by default, but I regularly use 800 entries without problem. My
history size is set to 1000, though I tend to top out at about 600-800 active directories).
This tool actually comes in two parts: the setdir executable, and the go batch file (which you
will normally use). setdir determines the commands needed to change to the target path (including
drive letter changes and remote share connections), and go executes these commands. (This
indirection is necessary because environment changes in an executable file don't change the shell's
environment.)
To use setdir, place the files setdir.exe and go.bat in a directory on your executable path.
If you immediately use setdir, it will create the file %USERPROFILE%\setdir.dat to track your
directory history. Alternatively, you can set the SETDIR environment variable to a filename of
your choosing, and setdir will use that as the setdir history data file. Now just use go
instead of cd when you want to change directories.
Several arguments can take wildcard patterns. All patterns are case-insensitive, and may contain the
characters * (matches zero or more of any character) and ? (matches exactly one character).
Print help reference information.
Print debug output. This allows you to watch over setdir's shoulder to see what it's doing, and is
also useful for understanding the heuristics it employs to search for the matching path.
Removes all historic paths that no longer exist. This is useful when you have a good sized history and want to clean out all obsolete paths. Running this occasionally will speed up your directory searches.
Print the setdir state (e.g. history size, automap, and so forth).
Set the size of the history stack. By default this is set to 200, though I like running with 1000 myself. The tradeoff of large stack sizes is the time it takes to look through all directories and all guesses before finding or failing to find anything.
Network path searches can be expensive, particularly if you are connected over a remote connection,
or some of the net shares are down. If netsearch is enabled, then setdir will perform all of the
various searches on network drives as it does for local drives. If netsearch is disabled (the
default), then it will only attempt those searches that have good odds of matching (e.g. if
you've already got a historical match).
If this is set true, and if you specify a network path, then
setdir will automatically map the network drive for you, and place
you in the requested directory. So, for example, you can do
go //foo/bar/xyzzy and it will work even if you don't currently have that
share mapped to any logical drive. setdir is fairly flexible in the
strings it takes for boolean values. For example, you can denote true with
true, yes, y, 1, or on.
If this switch is on, then the new directory will be printed when changing to a new directory. This is useful if you don't print the path in your shell prompt, for example. Reporting is off by default.
In verbose mode, setdir prints all shell commands before executing them.
Verbose is disabled by default.
If pattern is not given, prints all history entries. If pattern
is supplied, then print all matching history entries. The pattern is
implicitly prefixed with *.
Purges all entries from the directory history matching the given pattern. The
pattern must be supplied. This command is useful to remove all entries for a
particular network share, for example. For any given pattern, all entries
that match in the -list command will also match in the -purge command, so
you can double-check with -list before purging entries.
Go to history entry number num. To print history entries, use the
-list option.
The path to change to. Separating slashes in the directory paths may be either forward or backward
slashes. Also, if paths have single spaces in their names, you need not quote them (so you can do
something like go A dir name with spaces and go will automatically insert the spaces for you.
Paths may be one of the following types:
These are paths that begin with a drive letter and an absolute path, such
as G:/abc/def/ghi.
These are network paths that begin with two slashes, a machine name, another slash, and a share
point (e.g. //nostromo/mother/directives).
These are paths that begin with a slash. setdir will try to find the rooted path from every drive
you've been to. If netsearch is enabled, it will try this for network paths as well.
Paths that have no slashes at all, but are just simple strings.
Paths that don't begin with a root of any kind, but have multiple components (e.g.
xy/zzy/upstr).
If you supply a wildcard pattern, then setdir will test the pattern against all historical
entries. Note that the wildcard characters span slashes, so that foo*bar will match against
D:/aaa/foober/blah/bar.
setdir will explicitly not do speculative directory searches based on the
pattern; it will only check against places you've already been. This is to keep setdir as fast as
possible.
If you're interested in how setdir works, this section covers the basic strategy. Before searching
for the specified path, the slashes are normalized, the path fragments on the command line are
concatenated with spaces if necessary, and environment information (such as mapped network drives)
is gathered.
These are the following steps setdir takes as it tries to find the path (the first successful
match is the winner):
If the path string contains wildcard characters, then only the wildcard match is attempted. The
given pattern is tested against all historical entries. If a pattern doesn't match an entry, but the
same pattern concatenated with /* does, then the subportion of that path is tested and
used if available. For example, suppose the pattern is b*ghi, and we find an entry
C:\abc\def\ghi\jkl\mno, then it will fail to match, but b*ghi/* will match. In this
case, setdir will choose C:\abc\def\ghi as the winning entry.
The remaining tests are executed only if the path does not contain wildcard characters.
Try the path as is. This applies to all path types.
If the path is a rooted path (begins with a slash), then try rooting it to all visited local drives, and (if netsearch is enabled) all visited network paths.
See if the path matches the last portion of any historical path. For example, if the given path is
yon, we'll match on //harold/purple/crayon if that path is the most recent in the history that
ends in that string.
See if the path matches any partial path of a path we've visited. For example, if the given path is
ox/yz, we've been to C:/misc/things/box/morethings/stuff, and the directory
C:/misc/things/box/yz exists, then we'll match on the latter path.
See if the given path is a child of any directory we've visited. If netsearch is enabled, then do this for network paths as well.
If none of these attempts turn up anything, then we report failure and halt.
Also note that setdir will ignore matches that evaluate to the current directory. This allows you
to toggle between two directories that have the same name, like G:/jim/jam and X:/raspberry/jam,
by typing go jam from either of the directories.
One of the best ways to learn how setdir works is to turn on debugging output (via the -debug
switch) while changing to a given directory. You'll be able to watch which directories it tries and
which it guesses at. Here's an example session:
D:\srh\source\setdir> <b>go -debug icecap</b>
# Looking for setdir data file.
# Trying %SETDIR%.
# SETDIR is defined as "D:\srh\setdir.dat"; using that.
# Debugging output enabled.
# Current working directory is "D:/srh/source/setdir".
# Given path is "icecap".
# Current dir is "D:/srh/source/setdir".
# Straight Match?
# Trying icecap
# No.
# Tail Match: Been somewhere ending in "icecap"?
# No.
# Partial Path: A partial path of a historical path?
# No.
# Child Match: Subdirs of visited paths?
# (Skipping network paths.)
# Trying D:/srh/source/setdir/icecap
# Trying F:/appel2/tools/x86/sweeper/icecap
# Trying F:/appel3/src/qvlib/icecap
# Trying F:/ss/dxm/java/test/unit/3d/spin/icecap
# Trying F:/appel3/src/icecap
# Trying F:/appel2/src/icecap
# Trying F:/appelles/src/icecap
# Trying F:/appel2/src/appel/icecap
# Trying F:/appel2/tools/x86/perl/icecap
# Trying F:/appel2/tools/x86/directx/icecap
# Trying //itg1/contrib/gnu/tools/icecap
# Trying F:/appelles/src/appel/icecap
# Trying D:/apps/devstudio/vc/include/icecap
# Trying //lerp/c$/dxsdk/icecap
# Trying F:/appel2/icecap
# Trying F:/appel3/icecap
# Trying F:/appel3/tools/icecap
# Trying F:/appel2/src/appel/values/icecap
# Trying F:/appel2/src/appel/values/geom/icecap
# Trying F:/appel2/tools/x86/directx/inc/icecap
# Trying D:/srh/source/drives/icecap
# Trying F:/appelles/src/make/icecap
# Trying F:/appelles/icecap
# Trying F:/appelles/build/icecap
# Trying F:/appelles/build/win/icecap
# Trying F:/appelles/build/win/ship/bin/icecap
# Trying E:/nt/system32/icecap
# Trying E:/nt/icecap
# Trying F:/appel2/build/win/debug/bin/icecap
# Trying F:/icecap
# Trying F:/appel2/tools/x86/icecap
# Succeeded
# Writing history global for new path "F:/appel2/tools/x86/icecap".
# Wrote 710 entries.
# Writing commands to change to F:/appel2/tools/x86/icecap
# Local or mapped path.
F:\appel2\tools\x86\icecap>
Finally, here's a dump of a sample session to show some of the features of setdir. Note that we're
starting from scratch, with no prior history.
// This is our initial startup state.
C:\> go -state
histsize: 200
netsearch: false
automap: true
report: false
verbose: false
// Let's increase our history to 1000 entries.
C:\> go -histsize=1000
// Adding the first couple of paths to our history.
C:\> go /
C:\> go D:/
D:\> go c:/windows/system32
C:\WINDOWS\system32> go d:\bin\perl\bin
// Now list the history so far. Note that the entries are ordered newest
// first.
D:\bin\perl\bin> go -list
0: D:/bin/perl/bin
1: C:/WINDOWS/system32
2: D:
3: C:
// Now let's go to a UNC path. We don't currently have
// \\tikfiltoolbox\tools mapped, so `setdir` maps it to the first available
// drive letter and takes us there.
D:\bin\perl\bin> go //tkfiltoolbox/tools/586
The command completed successfully.
\\tkfiltoolbox\tools E:\586>
// Now let's try some shortcuts. Go to `32`, and note that it takes us to
// the most recent historial path that ended in `32`.
\\tkfiltoolbox\tools E:\586> go 32
C:\WINDOWS\system32>
// Now we'll go directly to a given directory entry.
// We'll use the second entry.
C:\WINDOWS\system32> go -list
0: C:/windows/system32
1: //tkfiltoolbox/tools/586
2: D:/bin/perl/bin
3: D:
4: C:
C:\WINDOWS\system32> go :2
D:\bin\perl\bin>
// Note that bad paths are handled as follows:
D:\bin\perl\bin> go foo
No matching directory found for `foo`.
// We're already at a directory ending in `bin`, so going to that string
// will take us to the most recent _different_ match.
D:\bin\perl\bin> go bin
D:\bin> go d:/srh/bin
D:\srh\bin> go c:/
C:\> go p*bin
D:\bin\perl\bin> go p*bin
No matching directory found for `p*bin`.
D:\bin\perl\bin> go s*bin
D:\srh\bin> go -list
0: D:/srh/bin
1: D:/bin/perl/bin
2: C:
3: D:/bin
4: C:/windows/system32
5: //tkfiltoolbox/tools/586
6: D:
D:\srh\bin> go ..
D:\srh> go /
// In the following example, setdir finds a new directory that is under a
// historical directory.
D:\> go notes
D:\srh\notes>
// Now purge all entries under with `C:/windows`. This is a good way to
// clear all entries to network paths you no longer care about. You can
// also use the -clean option to automatically purge all directories that
// no longer exist.
D:\srh\notes> go -purge c:/windows/*
Purging:
- C:/windows/system32
1 entry purged.
D:\srh\notes> go -list
0: D:/srh/notes
1: D:
2: D:/srh
3: D:/srh/bin
4: D:/bin/perl/bin
5: C:
6: D:/bin
7: //tkfiltoolbox/tools/586
Steve Hollasch / 2003-12-09