Cover V03, I06
Article
Listing 1

nov94.tar


Listing 1: fcd--an extension to cd

#################################################################
# This logic exits .kshrc if $FCD is already defined.  It keeps
# fcd from being called by subsequent subshells (.kshrc is run
# by ksh for each subshell). Make sure that these lines come
# before the definition of fcd but after anything else you want
# called in each ksh subshell.
#################################################################
if [ $FCD ]
then
return
else
FCD="fcd"
export FCD
fi

echo "Loading fcd- type \"fcd\" for information"

##################################################################
# function: addline(directory)
#----------------------------------------------------------------#
# Add line to file list for future lookup.                       #
##################################################################
addline()
{
error=0
echo "Enter full path of $Newline: \c"
read Fullpath
if [ -d $Fullpath ]
then
echo $Fullpath >> $HOME/fcd.list
Flist=$Fullpath
else
echo "Sorry, can't find that directory!"
error=1
fi
}

###############################################################
# function:usage
#-------------------------------------------------------------#
# Print a usage screen.                                       #
###############################################################
function usage
{
echo "Usage- fcd directory"
echo "       fcd -e directory for extended search"
echo "       fcd -p to add current directory to list"
echo "       fcd -r to recursively scan directories under current"
echo "\n\n"
}

#######################################################################
# function: fcd
#---------------------------------------------------------------------#
# Accept a string from the user and search for that string in Filedir.#
# "cd" to the found directory.                                        #
#######################################################################
function fcd
{
error=0
FileDir=$HOME/fcd.list
Duplist=$HOME/fcd.dup

###################################################################
# Print usage screen if no parameters given.
#
if [ $# = 0 ]
then
usage
return 0
fi

# Set expanded search flag.
Extend="NO"

###################################################################
# Handle special cases.
#
case $1 in
"-e")
###############################################################
# Toggle extended search mode.
#
if [ $# != 2 ]
then
echo "Error: insufficient parameters ($#)"
echo "Usage: fcd -e directory"
return 2
fi
Extend="YES"          # Init extended search flag on
shift                 # Make 2nd parameter 1st to skip "-e"
;;

"/")
###############################################################
# Go to root instead of searching for slash.  Slash is in every
# line of the database.
#
cd /
return 0
;;

"-p")
###############################################################
# Add current directory to fcd database.  Fcd returns right
# after this switch is passed (no other parameters are
# processed).
#
CurDir=$(pwd)

#
# Don't add a duplicate if directory is already in database.
grep "$CurDir\$" $FileDir > /dev/null
if [ $? != 0 ]
then
echo $CurDir >> $FileDir
return 0
else

echo "Current directory $CurDir\n is already in $FileDir"
return 1
fi
;;

"-r")
###############################################################
# Add all directories under current directory to the database.
#
echo "Scanning directories under $PWD"
find $PWD -type d -print >> $FileDir
cat "$FileDir" | sort | uniq > $Duplist
if [ $? = 0 ]
then
echo "Sorted and cleaned up $FileDir"
mv $Duplist $FileDir
fi
return 0
;;
esac

###################################################################
# Create a new database if none exists.
#
if [ ! -f $FileDir ]
then
echo "Creating new $FileDir in $HOME.  It may take a while..."
find $HOME -type d -print > $FileDir
fi

###################################################################
# Search in extended or regular mode for directory.
#
if [ $Extend = "YES" ]               # search full line for match
then
grep $1 $FileDir > $Duplist
else
grep $1'$' $FileDir > $Duplist   # search end of line for match
fi

###################################################################
# Count the matches found.
#
lines=`wc -l $Duplist | awk '{print $1}'`

###################################################################
# Process the matches
###################################################################
case $lines in
0)
###############################################################
# No matches. Let the user update the database, if desired..
#
echo "Not found- add(y/n)?\c "
read ans
if [ $ans = 'y' ]
then
Newline=$1
addline $Newline
if [ $error = 1 ]
then
return 1
fi
else
return 1
fi
;;

1)
###############################################################
# One match. Assign it to the cd list.
#
Flist=`cat $Duplist`
;;
*)
###############################################################
# More than one match.  Print a list for the user.
#
awk ' { printf "%2d : %s\n", NR, $0 }' $Duplist
echo "Which of the above do you mean (enter number or 'q' for none)? \c"
read lineno

###############################################################
# Get the line number from the user. 'q' is a special
# case to choose none.
#
if [ $lineno = 'q' ]
then
echo "Removing possible duplicates from file list..."
cat "$FileDir" | sort | uniq > $Duplist
if [ $? = 0 ]
then
echo "Sorted and cleaned up $FileDir"
mv $Duplist $FileDir
fi
return 1
fi

###############################################################
# Make the user enter 1-lines or q.
#
while [ $lineno -gt $lines -o $lineno -lt 1 -o $lineno = 'q' ]
do

echo "Valid input: 1-$lines or q.  Reenter number: \c"
read lineno
done

# Do nothing if user wants to quit.
if [ $lineno = 'q' ]
then
return 1
fi

###############################################################
# Pick the directory at the line the user chooses.
#
Flist=`sed -n "${lineno}p" $Duplist`
;;
esac


###################################################################
# Show the user the directory chosen in case they don't
# have "pwd" as part of the ksh PS1.
#
echo $Flist

###################################################################
# Go to the directory chosen.  This is actually the only
# line that MUST be run in the current process for fcd to
# work.
cd $Flist 2> /dev/null

###################################################################
# If cd failed, remove the defunct entry from the database.
#
if [ $? != 0 ]
then
echo "Removing defunct $Flist from $FileDir"
cat $FileDir | grep -v $Flist > $Duplist
if [ $? = 0 ]
then
mv $Duplist $FileDir
else
echo "An error occurred while editing $FileDir.  It may be damaged."
fi
fi
}

####################################################################
# Run the function the first time .kshrc is started.
fcd $1