2

If, in my newly created bash, I do:

pushd foo
pushd bar
dirs -l -v

I will get something like

0  bar
1  foo
2  old_dir

If I then do

bash
dirs -l -v

I get only

0  bar

The same thing happens if I use screen instead of bash.

How could I maintain the directory stack in the forked shell?

  • 3
    The directory stack is kept in the array variable DIRSTACK, so it should be a matter of exporting this variable. In fact, it looks like this variable is exported by default (checked with export -p). So this should work automatically! Well, it doesn't because of a known bash bug that prevents arrays from being exported (see section BUGS in the man pages) :S – ricab Sep 9 '13 at 13:16
1

The reason why this doesn't work automaticall ATOW is a known bash bug which prevents exporting array variables (see section bugs in man page). Unfortunately DIRSTACK is an array variable.

I created replacements for pushd/popd/dirs which wrap them but store their stuff in a scalar variable, so that children processes are aware of it.

If you source the code below and use mypushd/mypopd/mydirs instead of the originals, children processes will remember their parents' stack. Notice that this won't work with directories whose name includes a colon!

Please warn me if you spot any bug, 'cause I just wrote that. Also, if you know of a simpler alternative, please share!

export SCALARDIRSTACK
export DIRSTACK

update_dirstack()
{
  if [ ! -z "$SCALARDIRSTACK" ]; then
    dirs -c
    # get an array from scalardirstack
    IFS=':' read -a tmp <<< "$SCALARDIRSTACK"
    # traverse in reverse order to pushd stuff into the stack
    for (( idx=${#tmp[@]}-1 ; idx>=0 ; idx-- )) ; do
      # gotta use pushd/popd this to manipulate DIRSTACK
      pushd -n ${tmp[idx]} > /dev/null
    done
  fi
}

update_scalardirstack()
{
  if [ ${#DIRSTACK[@]} -gt 1 ]; then
    SCALARDIRSTACK=$(printf '%q:' ${DIRSTACK[@]:1}) # string from array
  else
    SCALARDIRSTACK=""
  fi
}

scalar_dstack_wrap()
{
  update_dirstack
  $@
  update_scalardirstack
}

alias mydirs='scalar_dstack_wrap dirs'
alias mypushd='scalar_dstack_wrap pushd'
alias mypopd='scalar_dstack_wrap popd'
  • backward shell compatibility aside, is there anything preventing one from using array (and thus getting rid of the separator issue (colon in this case)? – peterph Sep 9 '13 at 20:13
  • @peterph: the reason for the scalar workaround is apparent in my comment to the original question, but I updated the answer to reflect it as well, so that it is self contained – ricab Sep 10 '13 at 8:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.