(Far be it from me to go head to head against http://www.acm.org/classics/oct95/ Prof. Dijkstra but when I sent this to Stijn (who maintains http://micans.org/apparix/ apparix), he came up with this very cute title, which I promptly stole!)
Despite the title, this is nothing to do with programming, structured or otherwise :-)
This is all about supplementing the lowly cd command with some extra punch for those of us who spend a lot of time at the Linux command line working with files in various directories. Even with bash completion, typing out long directory paths is a chore that kills productivity.
This document has the following sections:
GOTO considered useful!!
First, a word about apparix
What is goto and where do I get it?
Features and uses
Dependencies/Caveats
Usage messages
Examples
Like in almost all things in this world, the http://en.wikipedia.org/wiki/Pareto_principle 80-20 rule applies. For the 20% of directories in which you spend 80% of your time, use the afore-mentioned http://micans.org/apparix/ apparix. For those cases, there's no substitute for the speed with which apparix works, the ability to set short names as bookmarks and to just say
to wh
instead of
cd /var/www/homepages/sitaram
The fact that setting bookmarks is just as easy also helps:
cd /home/sitaram/workdata/mindmaps
bm mm
bm and to are bash aliases that come with apparix. bm stands for bookmark.
For the other 80% directories where you spend 20% of the time, (and very cleverly, this can also be construed to mean "directories on other machines where you don't spend much time or you don't want to install apparix"!), use goto.
Get it from bashrc.goto and include it in your normal .bashrc
You get three bash functions: goto, fgoto, and goto_range. All of them will respond with a nice usage message if you give -h as the argument. Note that fgoto is really goto in disguise, but the argument is considered to be a file name pattern rather than a directory name pattern.
goto allows you to get some pretty major productivity gains very quickly, without having to install any software.
goto and fgoto make it easy to explore the filesystem looking for stuff whose location you only vaguely remember or guess.
Also, fgoto's ability to jump into a directory based on giving a filename (as opposed to a directory name) is unique. [If you know of other tools which do this, please let me know and I will be happy to acknowledge them; I haven't heard of any so far.]
When you know a good part of the file name, but are not sure where it lives, try fgoto. You'll be surprised!
Sometimes "goto" returns results from directories you don't care about, and you want to restrict the searches to a set of directories only. And sometimes it's the opposite – you want the results coming from anywhere except a certain set of directories.
Use the goto_range command for all this. The -h option shows you a pretty good help message.
This can be very useful sometimes. Ever inherited a whole bunch of files from someone else? Or downloaded a large-ish source tree with many directories and wanted to quickly jump around just within that, looking for files and directories?
Use goto . some_dir_pattern or fgoto . some_file_pattern to temporarily set the search range to the current directory before doing the goto/fgoto. When invoked this way, the current search range and all related settings are ignored.
In place of . (dot) above, you can use .., ~, or indeed any valid directory name, and you'll get matches only within that directory.
If you're curious, here're examples of the usage messages of the two functions goto and goto_range.
goto
[sitaram@home ~]$ goto -h
Usage: goto dir_pattern
fgoto file_pattern
Uses the locate database to find a directory (i) matching the dir_pattern OR
(ii) containing a file matching the file_pattern
The patterns use locate's "-r" option, except that we're only interested in
matching the last component of each candidate path.
argument matches what part of last path component?
------------ -----------------------------------------
path anywhere
/path starts with
path$ ends with
/path$ exact
IMPORTANT: You can restrict the search to one or more directories. Run
"goto_range -h" to learn how to use the search range effectively.
SHORTCUT: "goto . pattern" or "fgoto . pattern" TEMPORARILY sets the search
range to the current directory and then does the goto/fgoto, REGARDLESS of
what the current range settings are! You can do this with any directory
instead of "." -- I usually do this to ".", "..", "~", "/var" etc., as needed.
goto_range
[sitaram@home ~]$ goto_range -h
Usage: goto_range s|a|l|u|e|i
Sometimes "goto" returns results from directories you don't care about, and
you want to restrict the searches to a set of directories only
s = SET the current directory as the search range
a = ADD the current directory to the search range
l = LIMIT searches to the search range
the search range is set to the current directory if it is undefined
using the "s" or the "a" option automatically sets this also
u = UNlimited; use the entire locate database
the search range is not used even if it is defined
this is the default behaviour
Sometimes you want to say "search everywhere except in these directories"
e = EXCLUDE directories; search everywhere EXCEPT in search range
i = INCLUDE directories; search only in search range
this is the default behaviour
Here's how a few typical interactions might look like:
[sitaram@home ~]$ goto 6-misc-set2
/home/sitaram/save/pictures/mine/2006-misc-set2
[sitaram@home ~]$ fgoto img_2178
/home/sitaram/save/pictures/mine/2006-misc-set2
[sitaram@home ~]$ fgoto img_1878
1) /home/sitaram/save/pictures/mine/2005-friends
2) /home/sitaram/save/pictures/mine/2005-ganesh
#? 2
/home/sitaram/save/pictures/mine/2005-ganesh
Here's an example where it found multiple matches:
[sitaram@home ~]$ goto misc-set
1) /home/sitaram/save/pictures/mine/2006-misc-set1 5) /home/sitaram/save/pictures/mine/2005-misc-set2
2) /home/sitaram/save/pictures/mine/2006-misc-set2 6) /home/sitaram/save/pictures/mine/2005-misc-set3
3) /home/sitaram/save/pictures/mine/2006-misc-set3 7) /home/sitaram/save/pictures/mine/2005-misc-set4
4) /home/sitaram/save/pictures/mine/2005-misc-set1
#? 3
/home/sitaram/save/pictures/mine/2006-misc-set3
[sitaram@home 2006-misc-set3]$
Here's another example where it found multiple matches:
[sitaram@home ~]$ goto security
1) /home/sitaram/imli/files-pers/blog/blosxom-stuff/blosxom/software/security
2) /home/sitaram/.local/share/applications/Mandrakelinux/System/Configuration/KDE/Security
3) /etc/security
4) /var/lib/menu-xdg/applications/Mandrakelinux/System/Configuration/KDE/Security
5) /var/lib/menu-xdg/simplified/applications/Mandrakelinux/AdministerYourSystem/UseMoreAdministrationTools/Configuration/KDE/Security
6) /var/log/security
7) /usr/share/doc/HOWTO/HTML/en/Security
8) /usr/share/doc/HOWTO/HTML/en/Security-Quickstart
9) /usr/share/doc/HOWTO/HTML/en/Security-Quickstart-Redhat
10) /usr/share/ri/1.8/system/SecurityError
11) /usr/lib/libDrakX/security
12) /usr/lib/nvu-1.0/chrome/en-US/locale/global/security
#? ^C
Oops – too many matches, and from too many different places. I want to restrict the match to just the home directory. The long way is to use the goto_range command to set a range and then use the goto. The quick way is to just add a valid directory name (in this case just ~) as the first argument.
[sitaram@home ~]$ goto ~ security
range status: goto is currently limited
the range is defined to be
^/home/sitaram
run "goto_range -h" for usage
search range: ^/home/sitaram
1) /home/sitaram/imli/files-pers/blog/blosxom-stuff/blosxom/software/security
2) /home/sitaram/.local/share/applications/Mandrakelinux/System/Configuration/KDE/Security
#? 1
/home/sitaram/imli/files-pers/blog/blosxom-stuff/blosxom/software/security
[sitaram@home security]$
Remember: any valid directory is good for this trick, so the most common examples are things like are ., .., /etc, /var/www, etc.