pushd and popd

I'm learning about pushd and popd, and the section in my book defines them as functions to put in the .profile file, but I've noticed that the commands obviously already exist. I was wondering -- how do I find out where these commands are? Is there some kind other command/series of commands I can use to find out where these files are on my system?

Hi.

pushd and popd are shell built-ins available in bash and csh and possibly other shells (but afaik, not ksh). It's unlikely that you will find these "files" anywhere on your system.

If they are not available in the shell you are using, you could simulate them using functions in your .profile as your book suggests.

man builtin
man pushd

Okay, here are the two functions for pushd and popd:

DIRSTACK=""
export DIRSTACK
pushd ()
{ 
      dirname="$1"
      DIRSTACK="$dirname ${DIRSTACK:-$PWD' '}"
      cd ${dirname:?"missing directory name."}
      echo $DIRSTACK"

popd ()
{
     DIRSTACK=${DIRSTACK#* }
     cd ${DIRSTACK%% *}
     echo "$PWD"
}

When I try popd I get a message saying that the last directory pushed onto the stack I get message saying "No such file or directory," Even though I'm in that directory. I don't know what's going on. Can anyone help me?

The book is "learning the bash shell, third edition," if that helps.

That implementation of pushd/popd definitely isn't going to work for directories with spaces. And adds directories to the stack even when the directory does not exist. And if you have them already, you don't need them in your profile at all. What shell are you using?

I'm using the bash shell.

You don't need them in your profile at all.

In other words - you already have them - they are part of bash.

I know they already exist -- I'm learning about shell scripts right now and the book gives these as an example. I just wanted to know out of curiosity why the popd function isn't working they way it should.

I just noticed:

pushd ()
{ 
      dirname="$1"
      DIRSTACK="$dirname ${DIRSTACK:-$PWD' '}"
      cd ${dirname:?"missing directory name."}
      echo $DIRSTACK"
}

popd ()
{
     DIRSTACK=${DIRSTACK#* }
     cd ${DIRSTACK%% *}
     echo "$PWD"
}

missing a brace.

That was an older version of the code here's the newer one:

DIRSTACK=""
export DIRSTACK
pushd ()
{ 
      dirname=$1
      echo the value of dirname is "$@"
      if   cd ${dirname:?"missing directory name."} #if cd was successful
      then
           DIRSTACK="$dirname ${DIRSTACK:-$PWD' '}"
           echo "$DIRSTACK"
      else
           echo still in $PWD
      fi
}

popd ()
{
     DIRSTACK=${DIRSTACK#* }
     cd ${DIRSTACK%% *}
     echo "$PWD"
}

But it still doesn't work right.

Overriding the function of a shell builtin may itself not work properly. Also, the DIRSTACK variable already exists in bash -- as an array, not a flat string. You really should try them in a shell that doesn't have pushd and popd as builtins, like ksh, or busybox/ash.

Also:

${DIRSTACK:-$PWD' '}

Is this literally as the code has it? That seems odd. When I remove the ' ' it works in busybox ash shell.

Okay, I got a head of myself with this. I thought the DIR_STACK was a typo in my book and assumed it mean DIRSTACK, but it's not. So I'm starting over again and here's the code from the book, which I put in my .profile. The purpose of this excercise is to implement a stack as an environment variable containing a list of directories separated by spaces.

DIR_STACK=""
export DIR_STACK

pushd ()
{
   dirname=$1
   DIR_STACK="$dirname ${DIR_STACK:-$PWD' '}"
   cd ${dirname:?"missing directory name."}
   echo "$DIR_STACK"
}

popd ()
{
    DIR_STACK=${DIR_STACK#* }
    cd ${DIR_STACK%% *}
    echo "$PWD"
}

Now, the book said to put the DIR_STACK="" and export statement into my .bass_profile file which I don't have -- or, if I'm correct it is in fact my .profile file (which is one of the three files UNIX reads, according to the book, when you log in -- as that the same as exiting and opening a new window?)

So, I've copied the code and tried it out -- for example, I tried pushd to my Mail directory in my home directory. This is the result:

Mail/ /Users/chrislandalusa' '

why does it include the ' '?

if I try popd I get this result:

-bash: cd: /Users/chrislandalusa': No such file or directory
/Users/chrislandalusa/Mail

I don't need to specify the directory I want to pop, correct?

If I understand the code correctly, the first time I pushd, since the value of DIR_STACK is null, it prints PWD and the two single quotes, preceeded by the name of the directory that follows pushd.
But then, when I try another directory with pushd, like the inbox directory inside the mail directory, the mail directory is gone:

pushd inbox/
inbox/ /Users/chrislandalusa' '

Where did the Mail directory go?
And if I try popd I'll get a similar message

Even though there are deficiencies in the code for now (which the book says there are), I'd like some input as to what's going on -- maybe a step by step explanation of each line -- it may well be that these problems are inherent in the code and will be addressed later in the book.

---------- Post updated at 05:08 PM ---------- Previous update was at 04:55 PM ----------

Okay, I just tried something and changed the ' ' to " " and it worked.

So was that a typo in the book? what do single quotes do as opposed to doube quotes?

or is it supposed to be single quotes and I'm missing something?

---------- Post updated at 05:25 PM ---------- Previous update was at 05:08 PM ----------

another update

I figured out I'm getting the "no such directory error" because there are spaces between the directory names.

---------- Post updated at 07:27 PM ---------- Previous update was at 05:25 PM ----------

Corona --

Yes, that's what's in the book, but I changed them to " " and it worked (I posted this about a couple of hours ago as I write this). I'm guessing that it was a typo. Take a look at my most recent post and tell me what you think about my most recent discoveries about this and tell me what you think.

The book is about the bash shell, by the way.