May the source be with you, but remember the KISS principle ;-)
Home Switchboard Unix Administration Red Hat TCP/IP Networks Neoliberalism Toxic Managers
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and  bastardization of classic Unix

Advanced Unix Filesystem Navigation

News Recommended Links OFM Norton Change Directory
(NCD) clones
screen cdpath Bash history and bang commands
pushd/popd/dirs History reuse Readline and inputrc Directory favories Command completion Brace Expansion Bash Built-in Variables
Organizing shell aliases into knowledge database            
ln Dotfiles Care and Feeding of Functions in Shell bash Tips and Tricks  Unix shells history Humor Etc

There are a surprising number of wrong ways to get from one point of Unix filesystem directory to another and the only one right way (to use orthodox file manager style file manger  ;-). None of commercial versions of Unix/Linux have OFM installed by default, so in large enterprise environment you need either to install it on all servers or imitate it with other tools.   The simplest way might be imitate it with screen which is installed by default on several Linux distributions and is available in vendor supported packages for all major Unixes.

If you do not have mc or similar OFM the first step in increasing you productivity would be to use aliases and capabilities of CDPATH. Collection of aliases should generally be treated similarly to favorites in browsers:  and it make sense to keep it in a separate file or even a directory with multiple files.  You can also imitate favorites using symlinks, but never do it from you home directory. Use a separate directory like /fav. In case you use you home directory operations like chown -R myself * might have a disastrous effect on the system.  

cd command by-and-large outlived its usefulness for accessing complex directory maze ;-)

While cd command is really outdated and belongs to previous century as a way to navigate complex maze of directories typical for modern enterprise Unixes/Linuxes, it usage can be enhanced to make it more tolerable and less "clicks wasting" instrument.  There are multiple way or make it shorter for accessing deeply nested directory.

Unlike its more modern counterparts such as NDD, cd command does not has no its own history. Still there is access to previous directly used: entering cd - returns you to the last directory we used; entering it a second time "toggles" us back again). This might be more or less convenient way to work between two directories but it does not scale to three directory or more directories though.  

Another useful shortcut is cd which is built in alias for cd ~. It returns you to your home directory ( "~" is a shortcut for your home directory as defined by $HOME like in  . ~/.profile).  You can manipulate this point of return by changing variable $HOME but this is somewhat of a stretch...

Designers of  later versions of Unix OS and developers of second generation shells like ksh93 understood that something is wrong here but never were able to figure out what actually is wrong. \

The variable CDPATH defines the search path for the directory containing directories. So it served much like "directories home". The dangers are in creating too complex  CDPATH.  Often a single directory works best. For example export CDPATH = /srv/www/public_html . Now, instead of typing cd /srv/www/public_html/CSS I can simply type: cd CSS

Attempts to enhance the functionality of cd command

Naive and inconsistent attempts to fix the problem can be seen in various Unix commands. Historically the first was the introduction of  pushd/popd/dirs  troika in C shell. The idea was brilliant like many innovations introduced by Bill Joe in C-shell (he beat crap out of the while AT&T shell development team, especially out , but its implementation is almost useless as the data structure used (stack) is not very conductive to the task and there is no obvious way to imitate favorites with this troika.  Another negative factor is that instead of extending cd command in pretty obvious way three new were introduced. Later in Korn shell a limited version on return to prev directory was implemented as cd -. 

The second command that was enhanced to simplify navigation in Unix was "cd with replacement":

cd [new] [old]

This is ksh only trick, but this is very nice trick if you get used to it.  This form of "cd" takes two arguments. The first argument is a string to insert in the previous cd [whatever] command, and the second argument is the string we want it to replace.

For example, if we'd last typed

cd /spam/DB/etc

Then we could jump over to  /spam/Logs/etc by entering

cd DB Logs

If directory is not given, the value of the HOME shell variable is used.

But the most successful (albeit very limited) attempt to simplify navigation in Unix was the introduction of the variable CDPATH.  If the shell variable CDPATH exists, it is used as a search path. If directory begins with a slash or dot, CDPATH is not used.

As we mentioned before in cd command if  the directory is `-', it is equivalent to $OLDPWD.

The return status is zero if the directory is successfully changed, non-zero otherwise.

Pathname Completion

The shells ksh and bash both provide another useful feature, which, among other things, can help us get across directories. These shells have the ability to "guess" the directory name you're typing after you've typed the first few characters. Here's an example.

cd /usr/loc

and stop there, before entering the text, and then type TAB in bash (or the escape key twice in ksh), the shell completes the pathname for us:

cd /usr/local/

and the cursor waits at the end of the line for us to add the next part of the path. After some practice, pathname and filename completion can save a lot of keystrokes!

What happens if there are two or more directories that match the part we've typed? For instance, if we enter

cd /usr/lo

and type the escape key twice, no completion is performed. This will happen whenever the text we've entered matches two or more possible directories in the given path.

In this case, we can type the sequence [esc][=] instead. The following text is then displayed:

$ cd /usr/lo
1) local/
2) lost+found/
$ cd /usr/lo

what's happened is that a list of the possible selections that match the text is displayed. The unfinished command is reprinted, and the cursor waits for us to add some additional characters so we can complete enough of the pathname for completion to work properly.

bash needs no equivalent for the [esc][=] sequence, since it will automatically generate a list of possible entries if more than one exists:

bash$ cd /home/j
john jrl jsiler
bash$ cd /home/j

For more information about pathname completion see Command completion

You can use screen to provide multiple points of view of the filesystem

The first successful implementation of the ability to have multiple points of view on the filesystem was  screen.  Often the administrator work concentrates in a handful of directories (/etc/, /var/log and couple of others). Screen permits to preserve the context of each directory by having multiple virtual screens, one for each key directory.  In other words instead of using cd command you can open another session and then switch between multiple sessions.

Usage of .inputrc to scroll cd history

One of things I most often find myself doing is searching my command history for previous cd commands. With the two line addition to the standard /etc/inputrc or to you private ~/.inputrc, you can type in the first few letters, say "cd  " (note trailing space) and press PageUp and PageDown keys and it will scroll through your cd commands history. In order to get this functionality you need to add  the following two commands:

"\e[5~": history-search-backward
"\e[6~": history-search-forward

See Readline and inputrc for more information.

Note: escape codes for PageUp and PageDown vary depending on your terminal type; check out this tip for a technique on how to find out what your terminal expects.

Using multiple windows with one window containing automatically update list of file in the other

The first really useful way to enhance Unix navigation was introduced by John Socha in his  famous Norton Commander functionality of which was later generalized in the concept of orthodox file managers(OFM).  Later it was enhanced by incorporating  functionality of Norton Change Directory (NCD). The latter has multiple Unix clones. See (Norton Change Directory (NCD).

Large part of OFM functionality can be emulated in screen or even in two regular terminal windows (the idea of automatically updatable list of files is especially easy to implement.

The most popular OFM for Unix is mc (Midnight Commander). MC has a very primitive terminal window emulator which might annoy seasoned administrators, but one can also use mc as ncd -- launch it, navigate to the necessary directory and then exit (F10).

Static set of directory favorites via pushd and use dirs to access them

One of the most productive ways of usage of pushd/popd/dirs troika is to use it as a proxy to the directories favorite list.  To do this we need better  understand the capabilities of each of the commands  in pushd/popd/dirs troika

dirs [+N | -N] [-clvp]
Display the list of currently remembered directories. Directories are added to the list with the pushd command; the popd command removes directories from the list.
Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero.
Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero.
Clears the directory stack by deleting all of the elements.
Produces a longer listing; the default listing format uses a tilde to denote the home directory.
Causes dirs to print the directory stack with one entry per line.
Causes dirs to print the directory stack with one entry per line, prefixing each entry with its index in the stack.
popd [+N | -N] [-n]
When no arguments are given, popd removes the top directory from the stack and performs a cd to the new top directory. The elements are numbered from 0 starting at the first directory listed with dirs; i.e., popd is equivalent to popd +0.
Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero.
Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero.
Suppresses the normal change of directory when removing directories from the stack, so that only the stack is manipulated.
pushd [dir | +N | -N] [-n]
Save the current directory on the top of the directory stack and then cd to dir. With no arguments, pushd exchanges the top two directories.
Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated.
Makes the current working directory be the top of the stack, and then executes the equivalent of `cd dir'. cds to dir.
An array variable (see section Arrays) containing the current contents of the directory stack. Directories appear in the stack in the order they are displayed by the dirs built-in. Assigning to members of this array variable may be used to modify directories already in the stack, but the pushd and popd built-ins must be used to add and remove directories. Assignment to this variable will not change the current directory. If DIRSTACK is unset, it loses its special properties, even if it is subsequently reset.

dirs command is very useful if we try to use pushd/popd as a favorites list. If nothing else it provides you with the list of favorites: small but useful improvement over pitiful standard bash mode ;-).  To put directory into the stack you can use the ability to use pushd simply store directories using option -n.   Initial population of the list of favorites can be done in the .profile  from predefined list.  

After  populating the DIRSTACK you can use shortcuts to directories via cd ~1, cd ~2, ... notation.   For example if :
   dirs -v
       0  ~
       1  /var/log
       2  /usr/local

      cd ~1  is equal to cd /var/log
      cd ~2  is equal to cd /usr/local


Automatic maintenance of directories favorites

The first successful implementation of the idea of reusable history of visited directories as a basis for advanced navigation was implemented in Xtree.  There are several good Xtree clones for Unix so one can try to use this concept. See for example UnixTree, and Ytree. As they say on the webpage "Don't leave $HOME without it!"

Dr. Nikolai Bezroukov

Top Visited
Past week
Past month


Old News ;-)

[Feb 04, 2017] Use CDPATH to access frequent directories in bash - Mac OS X Hints

Feb 04, 2017 |
The variable CDPATH defines the search path for the directory containing directories. So it served much like "directories home". The dangers are in creating too complex CDPATH. Often a single directory works best. For example export CDPATH = /srv/www/public_html . Now, instead of typing cd /srv/www/public_html/CSS I can simply type: cd CSS
Use CDPATH to access frequent directories in bash UNIX
Mar 21, '05 10:01:00AM • Contributed by: jonbauman

I often find myself wanting to cd to the various directories beneath my home directory (i.e. ~/Library, ~/Music, etc.), but being lazy, I find it painful to have to type the ~/ if I'm not in my home directory already. Enter CDPATH , as desribed in man bash ):

The search path for the cd command. This is a colon-separated list of directories in which the shell looks for destination directories specified by the cd command. A sample value is ".:~:/usr".
Personally, I use the following command (either on the command line for use in just that session, or in .bash_profile for permanent use):

This way, no matter where I am in the directory tree, I can just cd dirname , and it will take me to the directory that is a subdirectory of any of the ones in the list. For example:
$ cd
$ cd Documents 
$ cd Pictures
$ cd Preferences

[ robg adds: No, this isn't some deeply buried treasure of OS X, but I'd never heard of the CDPATH variable, so I'm assuming it will be of interest to some other readers as well.]

cdable_vars is also nice
Authored by: clh on Mar 21, '05 08:16:26PM

Check out the bash command shopt -s cdable_vars

From the man bash page:


If set, an argument to the cd builtin command that is not a directory is assumed to be the name of a variable whose value is the directory to change to.

With this set, if I give the following bash command:

export d="/Users/chap/Desktop"

I can then simply type

cd d

to change to my Desktop directory.

I put the shopt command and the various export commands in my .bashrc file.

[Dec 15, 2014] CLI Magic Bash complete By Shashank Sharma

May 08, 2006 |

The auto complete feature of the Bourne Again SHell makes bash one of the most loved and newbie-friendly Linux shells. Just by pressing the Tab key you can complete commands and filenames. Press the Tab key twice and all files in the directory get displayed. But you can do more with autocomplete -- such as associating file types with applications, and automatically designating whether you're looking for directories, text, or MP3 files. With simple commands such as complete and the use of Escape sequences, you can save time and have fun on the command line.

You can use the dollar sign ($), tilde (~), and at (@) characters along with the Tab key to get quick results in autocomplete.

For instance, if you want to switch to the testing subdirectory of your home directory, you can either type cd /ho[Tab]/tes[Tab] to get there, or use the tilde -- cd ~tes[Tab]. If the partial text -- that is, the portion before you press Tab -- begins with a dollar sign, bash looks for a matching environment variable. The tilde tells bash to look for a matching user name, and the at-sign tells it to look for a matching hostname.

Escaping is good

The Tab key can complete the names of commands, files, directories, users, and hosts. Sometimes, it is overkill to use the Tab key. If you know that you are looking for a file, or only user names, then use the Escape key instead for completion, as it limits bash's completion field.

You can use several Escape key combinations to tell bash what you are looking for. Invoke Escape key combinations by pressing a key while keeping the Escape key pressed. When looking for a file, you can use the Esc-/ (press / along with Escape) key combination. This will attempt filename completion only. If you have one file and one directory beginning with the letter 'i,' you will have to press the Tab key twice to see all the files:

$ less i <tab><tab>
ideas im articles/

When you type less i and press '/' while keeping the Escape key pressed, bash completes the filename to 'ideas.'

While Control key combinations work no matter how long you keep the Ctrl key pressed before pressing the second key, this is not the case with Escape key sequences. The Esc-/ sequence will print out a slash if you delay in pressing the / key after you press the Escape key.

You can also use Escape along with the previously discussed $, ~, and @ keys. Esc-$, for example, completes only variable names. You can use Esc-! when you wish to complete command names. Of course you need to press the Shift key in order to use any of the "upper order" characters.

Even smarter completion

By default, Tab completion is quite dim-witted. This is because when you have already typed cd down before pressing Tab, you'd expect bash to complete only directory names. But bash goes ahead and displays all possible files and directories that begin with 'down.'

You can, however, convert bash into a brilliant command-reading whiz. As root, edit the /etc/bash.bashrc file. Scroll down to the end of the file till you see the section:

# enable bash completion in interactive shells
#if [ -f /etc/bash_completion ]; then
#    . /etc/bash_completion

Uncomment this section and voilà, you have given bash powers far beyond your imagination! Not only is bash now smart enough to know when to complete only directory names, it can also complete man pages and even some command arguments.

Don't despair if you don't have root previleges. Just edit the last section of your ~/.bashrc file.

Associating application with file types

The complete command in bash lets you associate file types with certain applications. If after associating a file type to an application you were to write the name of the application and press Tab, only files with associated file types would be displayed.

complete -G "*.txt" gedit would associate .txt files with gedit. The downfall of using complete is that it overwrites bash's regular completion. That is, if you have two files named invoice.txt and ideas.txt, gedit [Tab][Tab] displays both the files, but gedit inv[Tab], which should complete to invoice.txt, no longer works.

complete associations last only for the current bash session. If you exit and open a console, gedit will no longer be associated with .txt files. You need to associate file types to applications each time you start a new console session.

For permanent associations, you need to add the command to one of the bash startup scripts, such as ~/.bashrc. Then, whenever you are at the console, gedit will be associated with .txt files.

Shashank Sharma is studying for a degree in computer science. He specializes in writing about free and open source software for new users.

[Mar 30, 2009] Bash Navigation Toolkit

A prototype for directory favorites and navigation using bash by Richard Landon. In the current version is pretty much useless -- not batter then pushd/opod/dirs with static list of directories. The key idea is not new: using a PATH-like variable for string user-defined set of directory favorites which then can be addresses by their relative position in the list (1, 2, 3, etc). For example jump 3 will get to the third directory. This can be emulated by cd ~3 using pushd/popd/dirs troika.

The Bash Navigate Toolkit provides a set of functionality that allows users of the Bash (or Korn) shell to create and use sets of directory "favorites." These functions allow simple navigation within the file system, as well as deployment of automated scripts to iterate directories and perform various activities.

20-March-2008: Richard Landon -- A prototype for directory favorites and navigation using bash
               This prototype is provided AS-IN, with no warranty either expressed or implied.

   Various attempts to define a mechanism or tools for assisting with directory navigation
   have not been satisfactory in the opinion of the author.
   Various examples are cite in the URL

   Developed a solution more suitable to the authors needs for navigation and manipulation of a class of directory

   The basic idea behind this solution is to represent the history of directory navigation (favorites) using
   an environmental variable that follows the design of standard PATH variables common to Unix systems.
   The format of PATH related variable (such as path) is as follows: ::...:
   Various mechanisms (in the form of bash functions) were developed to assit the author with routine navigation
   commands. These include recording a directory favorite, and then navigating to that favorite with a simple 
   command or set of commands.  

      .navigate --  The navigation command set implementation
      .navigaterc -- A persistent record of navigation favorites (kept in the users home directory)

   1) Developed under Cygwin platform.
   2) GNU version of cut is available

    List the current value of the SET_HOME environment variable

   showhome [position]  
    Show the value of the [index] component in the navigation structure
    Default [index] is first (1) component

  filterhome [path]
     Determine if the structure contains the path; returns 0 under this case
     [path] is required. Used internally to filter additions to the structure
     (see sethome for more details). Probably not otherwise useful.
  sethome [path]
    Add the given [path] or current path (`pwd`) to the top of the navigation structure.
    [path] will be added only if it does already exist within the navigation structure.
    If specified path does not exist, it is ignored

    Completely remove the current navigation structure from the environment.

  unsethome [position] 
    Remove the element at the indicated [position] (defaults to first, 1) within
    the navigation structure. 

  jumphome [position]
    Navigate (cd, change directory) to the indication position (defaults to first, 1) within
    the navigation structure. If position is greater than the largest element, then the 
    command will navigate to the last location in the structure. Command ouputs the absolute
    path to the location of the request position (ie, the target directory)
    Displays in a readable format an enumerated list of the elements within the navigation structure.
    Each element has the form d:)path, where d is a digit (index) and path is a fully-qualified
    path element.

    Save the current navigation structure on disk. Output is written to the .navigaterc  file in
    the user home directory. The persistent navigation structure can be loaded later later using the
    loadhome command.
     Load a persistent navigation structure from disk into the environment. A persistent navigation
     structure can be stored to disk using the persisthome command. The environment is loaded
     using the contents of the .navigaterc file from the user home directory.

     Remove the currently persisted navigation structure from disk. This 

Standard alias
   The following standard set of aliases are provided for convenience 
   show  => showhome
   push  => sethome
   pop   => unsethome
   jump  => jumphome
   homes => listhomes
   load  => loadphome
   purge => purgehome
   reset => resethome

   Here are some basic examples that use the standard aliases to demostrate the usefullness of the commands
   Some actual data in the listing has been converted to protect privacy of author

(1) List current favorities and display environmental variable
mylocalhost: [~] {52} $ homes
mylocalhost: [~] {53} $ showhome

(2) Add a directory to the favorites
mylocalhost: [~] {54} $ push /usr/local/bin
mylocalhost: [~] {55} $ ls `jump 1`
bashdb-3.1-0.09/  bn

(3) Load persistent favorites from disk
mylocalhost: [~] {56} $ cat ~/.navigaterc
mylocalhost: [~] {57} $ load
mylocalhost: [~] {58} $ homes

(4) Navigate around favorites
mylocalhost: [~] {60} $ jump 3
mylocalhost: [buildScripts] {61} $ 

(5) Clear the current set of favorites
mylocalhost: [~] {60} $ reset
mylocalhost: [buildScripts] {66} $ homes
mylocalhost: [buildScripts] {67} $ showhome

(6) Show integration with standard Unix pipes and filters
mylocalhost: [buildScripts] {68} $ push $(which tar| xargs dirname) 
mylocalhost: [buildScripts] {69} $ homes
mylocalhost: [buildScripts] {70} $ jump 1
mylocalhost: [bin] {71} $ pwd
mylocalhost: [bin] {72} $ ls tar

(7) Display more favorites
mylocalhost: [bin] {73} $ cd
mylocalhost: [~] {74} $ homes

(8) Load persistent favorites (note: overwrites current list of favorites)
mylocalhost: [~] {75} $ cat .navigaterc
mylocalhost: [~] {76} $ load
mylocalhost: [~] {77} $ homes

(9) Add more favorites
mylocalhost: [buildScripts] {80} $ push $(which tar| xargs dirname)
mylocalhost: [buildScripts] {81} $ homes

mylocalhost: [buildScripts] {83} $ ls -l `jump 1`/tar
-rwxrwxrwx+ 1 RIRL mkgroup-l-d 295K Feb 28 19:54 /usr/bin/tar*

(10) Save updated favorites
mylocalhost: [buildScripts] {85} $ persist
mylocalhost: [buildScripts] {86} $ homes

mylocalhost: [~] {90} $ homes

(11) Remove a favorite 
mylocalhost: [~] {109} $ pop 2
mylocalhost: [~] {110} $ homes

(12) Reset all favorites
mylocalhost: [~] {112} $ reset
mylocalhost: [~] {113} $ homes

[Sep 27, 2007] Project details for Closebracket

This is essentially reinvention and re-implementation of OFM context sensitive linkage of extension to commands (via ext file) with he additional twist that if there is no extension file type (for example as discovered by file) is used.

Closebracket lets you define multiple shell actions in a single command to speed up the typing of the most repetitive shell commands. It includes ']' and '][' commands, which are located near the "Enter" key and are easy to type quickly. They invoke primary and secondary actions respectively.

wcd 3.1.6

kcd looks to better for Linux users

Sep 29, 2005 OS: MS-DOS/Windows 3.1/95/98/ME/NT/2000 License: Freeware

N/A Wcd is a program to change directory fast (another Norton Change Directory clone). It saves time typing at the keyboard. One needs to type only a part of a directory name and wcd will jump to it. Wcd has a fast selection method in case of multiple matches and allows aliasing and banning of directories. Wcd also includes a full-screen interactive directory browser with speed search. Features:

Phil Braham this not NCD variant but attempt to enhance pushd/popd functionality.



Bash scripts A replacement for cd. Keeps unlimited history, setup special directories for quick access

cdll allows easy moving about between directories. When changing to a new directory the current one is automatically put onto a stack. By default 50 entries are kept but this is configurable. Special directories can be kept for easy access - by default up to 10 but this is configurable. The most recent stack entries and the special entries can
be easily viewed.

The directory stack and special entries can be saved to, and loaded from, a file. This allows them to be set up on login, saved before logging out or changed when moving project to project.

In addition, cdll provides a flexible command prompt facility that allows, for example, a directory name in colour that is truncated from the left if it gets too long.

History of visited directories in BASH LG #109

Do you realize how many times you type cd per day? Do you realize how many times you retype the same directory names again and again? Ever since I migrated from 4DOS/NT shell on Windows to using Bash on Unix platforms, I've missed its cd history access. In 4DOS/NT the history of the visited directories can be navigated by Ctrl+PgUp/Dn. Every time you go to a new directory by cd, its name automatically goes on top of an easily accessible history list.

In Bash, cd - switches between the last two directories. This is a function in the right direction but many times I wanted to go to the directory before the last, I dreamed of something like cd -2.

A little scripting creates some sanity in the directory navigation of Bash.

Installing the CD history function

To install the modified CD function, copy to any directory in your $PATH, or even your home directory. At the end of your .bashrc add source Restart your bash session and then type cd --.

lotzmana@safe$ cd --
0  ~

Type cd -- to verify if the installation works. Above you may see the result 0 ~. This shows that you have one directory in your history.

lotzmana@safe$ cd work
lotzmana@safe$ cd scripts
lotzmana@safe$ pwd
lotzmana@safe$ cd --
 0  ~/work/scripts
 1  ~/work
 2  ~
lotzmana@safe$ cd -2
lotzmana@safe$ pwd

The cd command works as usual. The new feature is the history of the last 10 directories and the cd command expanded to display and access it. cd -- (or simply pressing ctrl+w) shows the history. In front of every directory name you see a number. cd -num with the number you want jumps to the corresponding directory from the history.

How CD with history works

lotzmana@safe$ nl -w2 -s' '
 1 # do "."
 2 # acd_func 1.0.5, 10-nov-2004
 3 # petar marinov, http:/, this is public domain

 4 cd_func ()
 5 {
 6   local x2 the_new_dir adir index
 7   local -i cnt

 8   if [[ $1 ==  "--" ]]; then
 9     dirs -v
10     return 0
11   fi

12   the_new_dir=$1
13   [[ -z $1 ]] && the_new_dir=$HOME

14   if [[ ${the_new_dir:0:1} == '-' ]]; then
15     #
16     # Extract dir N from dirs
17     index=${the_new_dir:1}
18     [[ -z $index ]] && index=1
19     adir=$(dirs +$index)
20     [[ -z $adir ]] && return 1
21     the_new_dir=$adir
22   fi

23   #
24   # '~' has to be substituted by ${HOME}
25   [[ ${the_new_dir:0:1} == '~' ]] && the_new_dir="${HOME}${the_new_dir:1}"

26   #
27   # Now change to the new dir and add to the top of the stack
28   pushd "${the_new_dir}" > /dev/null
29   [[ $? -ne 0 ]] && return 1
30   the_new_dir=$(pwd)

31   #
32   # Trim down everything beyond 11th entry
33   popd -n +11 2>/dev/null 1>/dev/null

34   #
35   # Remove any other occurence of this dir, skipping the top of the stack
36   for ((cnt=1; cnt <= 10; cnt++)); do
37     x2=$(dirs +${cnt} 2>/dev/null)
38     [[ $? -ne 0 ]] && return 0
39     [[ ${x2:0:1} == '~' ]] && x2="${HOME}${x2:1}"
40     if [[ "${x2}" == "${the_new_dir}" ]]; then
41       popd -n +$cnt 2>/dev/null 1>/dev/null
42       cnt=cnt-1
43     fi
44   done

45   return 0
46 }

47 alias cd=cd_func

48 if [[ $BASH_VERSION > "2.05a" ]]; then
49   # ctrl+w shows the menu
50   bind -x "\"\C-w\":cd_func -- ;"
51 fi

4-7: cd_func() is a function, variables are declared local and are automatically deleted at the end of the function

8-11: if the function is called with a parameter "--" then it dumps the current content of the directory history. It is stored in the same place pushd/popd keep names -- the directory stack. Storage is the same, access is different.

12-13: Argument $1 is transferred into $the_new_dir for some post-processing. Immediately after that, if there are no parameters we assume that user asked for his home directory.

14-22: If parameter begins with '-' then the user is attempting to access one of the names in the history list. $index gets the number of the directory, then we extract the corresponding name into $adir. For example, dirs +3 dumps directory #3 from the stack.

At this point in $the_new_dir we have either a name specified explicitly as a parameter or a name obtained from the history of previously visited directories.

23-25: If a directory name begins with '~' then this character has to be replaced by the actual home directory name.

26-30: pushd does the actual 'cd'. It also puts the name on top of the directory stack. stdout is redirected to /dev/null in order to completely imitate how 'cd' works. Notice that any output to stderr, for example a message telling that the directory specified by the user doesn't exist will show up, which is again similar to what 'cd' does. The function aborts if pushd fails. We also need the new directory name for further analysis and $the_new_dir carries it down the function.

31-33: Keeping track of more than 10 directories is unproductive. Since we have just pushed one on top of the stack, we trim off any that fall below 11 names deep.

34-44: We loop through all the names in the directory stack. Any name that matches the new current directory is eliminated. Again, we have to translate any name from the list which begins with '~' to its format of fully expanded home directory.

47: We assign cd to be cd_func().

48-51: If the bash version allows for macros to be assigned we make ctrl+w summon the history of visited directories.

This script defines a function. It must be sourced and not executed, so that cd_func() is parsed and stored in the current environment. Try env and you must see it after all environment variables.

Documentation page of the script

Visit the man page.

For comments on this article please visit or join zepp mailing list.
The text of this page is public domain.

[Mar 27, 2003] Accelerator for Changing Directory

An interesting idea of first letter abbreviations. Implementation can be better, but idea is sound.

Since I moved to Win XP my old and trusted companion for easily jumping between different spots in the directory tree, NCD (Norton Change Directory) has ceased to work.
NCD worked by building a database and by using NCD to make and remove directories, the database could be kept in sync, well almost anyway.
If the directory you wanted to go to had a unique name all you had to type was NCD dir_name but if it was a common name like test you might have had to recall the commandline one or more times to get to the destination.

Another approach would be to note that if you consider part of or the whole branch, from root to the destination, the situation will be less ambigous or even unique Using that idea I came up with this simple solution which IMHO works quite well. The user interface may be rendered idiosyncratic by some, but I welcome you to suggest improvements. The documentation is nothing fancy just a few examples included in the code. The program is tested under Win XP, but I think it could work on other OS's with some minor tweaks. PS. As directory delimiter "\", "/" or even "," can be used. The comma is due to laziness, because on the Swedish keyboard one has to use Shift or Alt Gr key to get slashes!!

So instead of typing
cd "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\Machin eKeys"
at the DOS prompt, typing the more dense command of
a ,d,a,a,m,c,r,m
will suffice. Or even horrors a ,d,,,,,r,m ;-), but that one is tougher on the filesystem.

@perl -Swx %0 %*
@goto :eof

# Utility for quickly changing directory
# Named to "a.bat" in homage to Pr1mOS's change working directory comm
+and *a* (attach) ;-]
# Syntax: 
#   a ,wi,ja,pa ===> cd \Windows\java\Packages
#   a ...\me    ===> cd \Windows\Media
#   a           ===> cd \Windows\Media\Microsoft Office 2000 *OR* a se
+lection of subdirectories
#   a /         ===> cd \
#   a mys,d,*
#   [a] /mysql/data/mysql/
#   [b] /mysql/data/tast/
#   [c] /mysql/data/test/
#   [d] /mysql/Docs/Flags/
#   select:
# if ambigous the correct target is selected with alpha keys /a .. zz/

# Versions:
# 0.2 2003-02-22 Cleanup
# 0.1 2003-01-31 First working
# 0.0 2003-01-15 Start of Coding

use strict;
use warnings;

use Cwd;

my $DEBUG = 0;
my $DELIM = qr{,|\\|\/};  ## Either "," or "/" or \" 
my @to = @ARGV ? split(/$DELIM/, $ARGV[0] ) : ();

my @cwd = split(/$DELIM/, cwd);
shift @cwd;  # Remove disk

unless ( @ARGV ) {
    push @to, @cwd, '*';
elsif ( $ARGV[0] =~ /^$DELIM/ and not @to ){ 
elsif ( $to[0] eq '' ) {
    shift @to;
else {
    unshift @to, @cwd;

## Lazy-dots
foreach my $part (0 .. $#to) {
    if ( $to[$part] =~ /\.(\.+)/ ) {
        $to[$part] = join('/',  ('..') x length($1));

@to = split(/\//, join('/', @to));

## Rel2Abs
my @fixed;
for (@to) {
    if ($_ eq '..') {
        pop @fixed if @fixed;
    } elsif($_ eq '.') {
        ## Skip
    } else {
        push @fixed, $_

my @choices = expand('/', @fixed);

my %hash;
my $enum = 'a';
my $choice = '';
if (1 == @choices) {    # Autoselect if only one item to choose
    $hash{a} = $choices[0];
    $choice = $enum;
} elsif(1 < @choices) {
    foreach my $c (@choices) {
        ($hash{$enum} = $c) ;
        print '[', $enum++, "] $c\n";
    print "select: ";
    $choice = <STDIN>;
    chomp $choice;

# Create a batch file to change the directory in the shell.
open (CD, '>', 'C:/A_CD.BAT') or die "Failed to create CD bat file $!\
if ( defined $hash{$choice} ) {
    $hash{$choice} =~ s/\//\\/g; # Make windows happy
    print CD "\@CD \"$hash{$choice}\"\n";
} else {
    print CD "\@echo No match\n";
close CD;

sub expand {
    my ($bough, @twigs) = @_;

    return $bough unless @twigs; ## Looked it up in the thesaurus ;-]
    opendir(my $dh, $bough) || die "Can not check $bough for twigs due
+ to $!\n";
    my $regexp = shift @twigs;
    $regexp =~ s/\*/.*/;
    my @found;  
    foreach my $f ( grep { $_ =~ /^$regexp/i and $_ !~ /^\./}  readdir
+($dh) ) {
        push @found, expand("$bough$f/", @twigs) if (-d "$bough$f");
    closedir($dh) || die "Bad close for $bough $!\n";
    return @found;


Backtracking with bash

This is a novice take or the subject, all info is wrong ;-)
I was working with linux quite a bit today, and frequently changing between directories, when I wondered if there was a way to go back to the directory I was in previously.

Turns out there is a way:

 cd ~-
So if I was doing something like this:
[pete@bigred /]$ cd /etc
[pete@bigred etc]$ cd /usr/local
[pete@bigred local]$ cd ~-
[pete@bigred etc]$ pwd
If you want to create a command so you don't have to type ~- you can create an alias:
alias cdb='cd ~-'
This ~- thing works great if you only need to go back one directory, but what if you wanted to go back two directories. Continuing the last code sample:
[pete@bigred etc]$ cd ~-
[pete@bigred local]$ cd ~-
[pete@bigred etc]$ pwd
We are back to /etc and not / our starting point. What I want is something that keeps a history of the directories I've been to.

It turns out that the Bash (the "Bourne again shell") has a directory stack builtin. Three command line tools for manipulating the stack are avaliable dirs, pushd, and popd. More info about the directory stack in bash here.

If we pushd a directory onto the directory stack, we can retreive the top of the stack using dirs +1. I tried setting up some aliases to get it to work the way I wanted:

alias cdd='pushd'
alias cdb='cd `dirs +1`'
Those worked a bit, but I ran into a lot of problems, especially when in the home directory. Also when you run pushd, popd, or dirs it always prints the contents of the stack, I don't know how to suppress that. So I figured I would post it here, and see if anyone can come up with a solution, or if anyone knows of a better way of going about this.

Isn't it funny how software developers will spend hours of time trying to save a few seconds of their future time.

| Add Comment | Linux


On 01/23/2004 at 01:19 AM John wrote:

cd - works. I don't think you need cd ~-.

On 04/24/2004 at 04:50 AM Pritam wrote:

You can suppress the output redirecting the output to /dev/null e.g. pushd <dir-name> >> /dev/null popd >> /dev/null

Recommended Links

Google matched content

Softpanorama Recommended

Internal links

External links



Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy


War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes


Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law


Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D

Copyright © 1996-2021 by Softpanorama Society. was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to to buy a cup of coffee for authors of this site


The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Last modified: February 21, 2017