#!/bin/tcsh # # dirstack This csh/tcsh script builds a directory stack for a login # shell from a file of previously stored directories. It # should be sourced, rather than executed. # # csh has a facility for saving a directory stack, but it is # geared towards single-shell use. This script is intended # for use in a windowing environment. # # requirements: # - There is a directory in the user's home directory called # ".sessions", which will hold the directory files. # # - There will be a shell variable "ttyname", which will be # the name of an individual terminal. (xterm, in my case.) # My .cshrc uses this line to set this variable: # # set ttyname = `xprop -id $WINDOWID WM_NAME | awk -F\" '{print $2}' | awk '{print $1}'` # # - The directory files are named "d-${ttyname}-". # So, for a terminal with a name of "devel", and an xterm # with a pid of 38911, the directory file's absolute path # will be ~/.sessions/d-devel-38911. # # - The directory files will be updated after every pushd/ # popd execution. I use these two aliases (and a few # other related ones) to accomplish this: # # alias dv "dirs -v | perl -p -e 's/^\d+\s+//'" # alias pd "pushd \!* ; dv > $dirsfile" # # usage: # $ source dirstack # # Revision History # 1.0 Initial revision. 140616 # 1.1 Handle directories with spaces properly. 150719 # 1.2 Get current directory files, not saved ones. 150809 # Changed directory files from "t-..." to "d-...". # 1.3 Renamed sessions directory from .ttys to .sessions. 150920 # 1.4 Added license info. 180616 # # Written by Wayne Morrison, 140616. # # Copyright 2014 Wayne Morrison # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # # If we have a ttyname, we'll dig out the tty's directory file and # add its directories to the shell's stack. # if("$ttyname" == "") then echo "no ttyname, cannot determine dirsfile" exit endif # # Set a "constant" for the directory of directory files. # set ttydir = ~/.sessions # # Get the number of directory files this tty has. # Old ones may still be hanging around... # # set dfcnt = `ls -1 $ttydir/d-${ttyname}-* | wc -l` set dfcnt = `ls -1 $ttydir/d-${ttyname}-* | egrep '[0-9]+$' | wc -l` if($dfcnt == 0) then echo "no current dirsfiles for $ttyname, so no directory stack to build" unset ttydir exit endif # # Use the most recent current directory file, if this tty has more than # one. (Also, older current directory files will be moved to save files.) # Otherwise, we'll use the solitary directory file we have. # if($dfcnt > 1) then # # These commented-out "set dirf" lines are the old way of doing things. # # set dirf = `ls -tr1 $ttydir/d-${ttyname}-* | tail -1` # set dirf = `ls -tr1 $ttydir/d-${ttyname}-* | egrep '[0-9]+$' | tail -1` # # Get the list of current directory files. # set dirflist = `ls -tr1 ~/.sessions/d-${ttyname}-* | egrep '[0-9]+$'` set savecnt = $#dirflist # # Move the old current directory files to be save files. # All but the most recent one, that is. # while($dfcnt > 1) set dirf = $dirflist[1] shift dirflist mv $dirf $dirf.save set dfcnt = $#dirflist end # # Save the most recent current directory files as the one to use. # set dirf = $dirflist[1] echo "too many current dirsfiles ($savecnt), using most recent - $dirf" echo '' unset dirflist savecnt else # set dirf = `ls -1 $ttydir/d-${ttyname}-*` set dirf = `ls -tr1 $ttydir/d-${ttyname}-* | egrep '[0-9]+$'` endif # # Get the number of lines in the directory file. # set dcnt = `wc -l $dirf | awk '{print $1}'` # # We'll push each directory in the tty's directory file onto the shell's stack. # The "tail" command pushes them in reverse order so we preserve the directory # order as found in the directory file. # We'll handle the cases where a directory name has a space. For them, any # tildes will be translated to the full path. Otherwise, the tildes will be # left alone. # foreach dl ("`tail -r -n $dcnt $dirf`") if (`echo $dl | egrep \ ` != '') then set gdl = `glob "$dl"` pushd "$gdl" > /dev/null unset gdl else pushd $dl > /dev/null endif end # # Get rid of the executing directory from the stack. # set firstdir = `dirs -v | tail -1 | awk '{print $1}'` if($firstdir > 1) then popd +$firstdir > /dev/null endif # # And let's see what we ended up with. # dirs -v | perl -p -e 's/^\d+\s+//' # # Move the directory file to a saved state. # mv $dirf $dirf.save # # Unset the shell variables we used here. # unset dcnt dfcnt dirf dl ttydir firstdir