USA Linux Users Group Forum Index
Log in Register FAQ Memberlist Search USA Linux Users Group Forum Index Album

Pushd, popd, and dirs in Bash

 
Post new topic   Reply to topic   printer-friendly view    USA Linux Users Group Forum Index » Command Line Commands
View previous topic :: View next topic  
Author Message
masinick
Linux Guru


Joined: 03 Apr 2024
Posts: 8615
Location: Concord, NH

PostPosted: Thu Oct 11, 2024 1:16 am    Post subject: Pushd, popd, and dirs in Bash Reply with quote

I yanked these tidbits out of a Linux Journal Email newsletter that I received today:

Quote:
This submission comes from Sangeeth from Bangalore, India:

The dirs command, combined with pushd and popd, is very effective for tracking users' directory changes. Suppose you have to make some changes to the files present in the following directories:
Instead of noting down the directories on paper, do the following:

Code:
$ pushd /home/sangeeth/soft/release2/src/

Code:
$ pushd /home/sangeeth/soft/release2/src/show/

Code:
$ pushd /home/sangeeth/soft/release2/doc/


To list all the directories, do the following:

Code:
$ dirs -l -p -d


The above command removes the topmost directory entry (/home/sangeeth/soft/release2/src/) and performs a cd to the new top directory, which in my case, will be the second directory (/home/sangeeth/soft/release2/src/show/).

Alternatively, one can pop a particular directory from the list of directories by giving the directory ID (the ID is displayed beside a directory when using dirs -l -p -d) to the popd command:
Code:
$ popd +1


More options available for using the above commands can be found by viewing the man pages.



_________________
Brian Masinick
Distros: SimplyMEPIS
sidux - no CAPS!, antiX, Debian
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
d_riordan
Member


Joined: 08 Jan 2024
Posts: 245
Location: Leominster, Massachusetts, U.S.A.

PostPosted: Thu Oct 11, 2024 6:11 am    Post subject: Reply with quote

I was a little puzzled about these commands for a minuet. Typing
Code:
man pushd

et. al. produced nothing on my Ubuntu laptop, but searching through
Code:
man bash

found them as builtin commands.

I'm less puzzled now, but I'm still trying to imagine where or why I would use them . . . Confused



_________________
*buntu 8.04
Back to top
View user's profile Send private message Visit poster's website
masinick
Linux Guru


Joined: 03 Apr 2024
Posts: 8615
Location: Concord, NH

PostPosted: Thu Oct 11, 2024 5:40 pm    Post subject: Use them for directory navigation Reply with quote

d_riordan wrote:
I was a little puzzled about these commands for a minuet. Typing
Code:
man pushd

et. al. produced nothing on my Ubuntu laptop, but searching through
Code:
man bash

found them as builtin commands.

I'm less puzzled now, but I'm still trying to imagine where or why I would use them . . . Confused


You would only use these commands if, first of all, you are a frequent shell user (Bash, or equivalent shell that has these functions - I believe a couple shells do have pushd, popd, and dirs functions). Secondly, even if you are a shell user, you use them only if you create a hierarchy of directories and navigate through them a lot.

Lately I rarely navigate directories. However, I implemented functions similar to these in the Korn Shell years ago, then ported them to my bash shell resource file, .bashrc.

Below are the contents of my .bashrc file. Note the functions g, gb, etc. These implement similar functions but use really short names for typing convenience.

Code:
# File: ~/.bashrc
# Author: Brian Masinick
# Created on: Fri Jan 06 09:26:19 2024

PS1="\u@\h\n\w \@ [\!] > "
export PATH=$PATH:/usr/local/bin:/usr/ccs/bin:~/bin:.

# Author:
#   Brian W. Masinick
# Purpose: Set resources, environment, alias, and prompts
#   for the Bash shell.
#   Defines variables, aliases, and functions for shortening typing
#   and tasks.  Used with the Bourne Again Shell, bash, from the GNU
#   project of the Free Software Foundation.
#
# NOTE: This file is an adaptation of my .kshrc file, removing things
# that are peculiar to the Korn Shell, ksh.
#
# Conventions:
#   I define every procedure and function using UpperCase Words Like
#   this and prepend each name with TheMas to reduce the likelihood of
#   a naming collision with a command, script, or program.

#   The procedures are invoked at the bottom of the file.  The
#   functions or procedures can be called at any time by any
#   procedure, which is why breaking the procedures and functions into
#   similar groupings makes sense.  The organization of the procedures
#   may need to be adjusted periodically to keep in step with my
#   current work.

# exit if not interactive

case "$-" in
*i*) ;;
*) return ;;
esac

TheMasPoolTools()   # define pool and tool directory variables
{

     #
     # define some aliases used with sandboxes and/or ODE
     #

     alias c=clear
     alias h=history
     alias qa1='ssh -l tssadm fpsfebtibqa1'
     alias qa2='ssh -l tssadm fpsfebtibqa2'
     alias kd="kdestroy"
     alias ki="kinit $PRINCIPAL"
     alias kl="klist"
     alias mm='make clean;make includes;make depend;make'
     alias title=~/bin/title

}

TheMasWebExports()       # define the environment variables to be exported.
{

     # export the CDROM location  so that it can be used from a
     # window manager.  Whenever an upgrade is performed, be sure to
     # do a chmod 644 /dev/cam and chmod 666 /dev/rrz4c.

     export CDROM=/dev/rrz4c
}

TheMasPrinters()   # define printer aliases
{

     #
     # Printing aliases...
     #

     alias lpd='lpr -P doc2 -K2 -N1'
     alias lp1='lpr -P doc1 -K2 -N1'
     alias lp2='lpr -P doc1 -K2 -N2'
     alias lp_doc1='lpr -P doc1 -K2 -N1'
     alias lpq_doc1='lpq -P doc1'
     alias lpq_doc2='lpq -P doc2'
     alias lp_l='lpr -P doc1 -O landscape'
}

TheMasMisc()       # miscelaneous aliases I like to use
{
     alias bye='clear; kill -1 0'
     alias c="clear;pwd"
     alias cls=clear sd=cd
     alias lo='clear;  kill -1 0'
     alias m='more'

     # miscelaneous miscelany...

     alias help=apropos
     alias wn='who -uT | fgrep .'

     # history aliases...

     alias h='fc -l'
     alias re='fc -e -'
     alias zaphist="rm -f /tmp/.mas_history"

     # host aliases...

     alias host=hostname
     alias rw="rwho | sort +1"

     # desktop office tool aliases...

     alias bh='exec /bin/bash'
     alias e=emacs
     alias kh='exec /bin/ksh'
     alias n=next
     alias null=~/null.bash
     alias p=prev
     alias R='repl -cc all -filter ~/.mhfilter'
     alias um=UnseenMail

}

TheMasFileManagement()   # commands I use to operate on files and dirs.
{
     # directory movement aliases...

     alias cd='g'
     alias home=cd

     # file management aliases...

     alias del="rm -i"
     alias copy=cp
     alias del='rm -i'
     alias dir="ls -aqFC"
     alias type=cat
     alias l='ls -aqCF'
     alias lsd='ls -algFqd'
     alias lsf='ls -F'
     alias lsi='ls -algFqi'
     alias lsl="ls -algFq"
     alias lsr='ls -aqCFR'
     alias lst="ls -algsFqt"
     alias lst10="lst | head -10"
     alias lst20="lst | head -20"
     alias lst30="lst | head -30"
     alias lst40="lst | head -40"
     alias lst50="lst | head -50"
     alias lst60="lst | head -60"
     alias lst70="lst | head -70"
     alias pdw=pwd
     alias pd=pwd
     alias wpd=pwd
}

TheMasTerm()
{

     alias vt52="TERM=vt52; export TERM"
     alias vt100="TERM=vt100; export TERM"
     alias vt102="TERM=vt102; export TERM"
     alias vt200="TERM=vt200; export TERM"
     alias vt300="TERM=vt300; export TERM"
     alias vt400="TERM=vt400; export TERM"
     alias xrs='set noglob; eval `resize -s \!\*`; unset noglob'
     alias xs='set noglob; eval `resize`; unset noglob'
}

TheMasWorkon()
{

     ####################################################################
     #
     # Tom Woodburn's stuff (adapted) below...
     #
     ####################################################################

     export HISTFILE=/tmp/.mas_bash_history
     export HISTSIZE=15000

     HOST=`hostname`
     # Strip off domain name; e.g., change flume.zk3.dec.com to flume.
     HOST=`expr "$HOST" : '\([^\.]*\)'`
     export HOST

   esac
#   PS1="[$HOST:(`whoami`) $SANDBOX($SET)] "
   # if DISPLAY exists, set titlebar and icon.
   if [ -n "$DISPLAY" ]; then
      ~/bin/title "Sandbox set $PS1 for $USER" $HOST
   fi
   unset LANG
   ;;
     esac
}

TheMasHosts()      # define host aliases...
{

     # rl is a procedure in my bin directory that alters the title bar,
     # then calls rlogin.

     alias fpsdevbld1='ssh -l tssadm fpsdevbld1'
     alias fpsfebtibqa1='ssh -l tssadm fpsfebtibqa1'
     alias fpsfebtibqa2='ssh -l tssadm fpsfebtibqa2'
     alias fpstibqa031='ssh -l tssadm fpstibqa031'
     alias fpstibqa051='ssh -l tssadm fpstibqa051'
     alias fpstibqa091='ssh -l tssadm fpstibqa091'
     alias fpstibqa092='ssh -l tssadm fpstibqa092'
     alias fpstibqa111='ssh -l tssadm fpstibqa111'
     alias fpstibqa112='ssh -l tssadm fpstibqa112'
     alias fpstibqa121='ssh -l tssadm fpstibqa121'
     alias fpsadpqa001='ssh -l tssadm fpsadpqa001'
}


#########################################################################
#
# Bill Gray's functions (adapted) below...
#
#########################################################################

# directory stack functions

declare -i DNUM=0
DLIST[DNUM]=`pwd`

function g      # go to a directory
{
   if builtin cd "$@" >/dev/null  &&  [ ${DLIST[DNUM]} != "$PWD" ]
   then
      DNUM=DNUM+1
      DLIST[DNUM]=$PWD
   fi
   case $WORKON in
   "")
   # if DISPLAY exists, then set titlebar and icon.
   if [ -n "$DISPLAY" ]; then
      titlebar="$USER @ $HOST : $PWD"
      ~/bin/title "$titlebar" "$HOST"
   fi
   ;;
   *)
   ;;
   esac
   pwd
}

function gb      # go back
{
   if (( $DNUM > 0 ))
   then
      DNUM=DNUM-1
   fi
   g ${DLIST[DNUM]}
}

function gn      # go to selected (nth) dir
{
   select DIR in `echo ${DLIST[*]} | tr " " "\012" | sort -u -y0`
   do
      if [ "$DIR" ]
      then
         g $DIR
      else
         g $REPLY
      fi
      break
   done
}

function up      # go up n levels
{
    declare -i levels

    levels=${1}

    if [ -z "${1}" ] && [ ${PWD} != "/" ]
    then
       g ..
       return $?
    fi

    while [ ${levels} -gt 0 ] && [ ${PWD} != "/" ]
    do
       g ..
       levels=levels-1
    done
}


function lpit
{
   for file in $*
   do
      pr -e8 -f $file | lpr -J $file -P doc1
   done
}

function lpsrc
{
   for file in $*
   do
      pr -e8 -f -n5 $file | lpr -J $file -P doc1
   done
}

function lp_2sides
{
   for file in $*
   do
      pr -e8 -f -n5 $file | lpr -J $file -P doc1 -K 2
   done
}

function lp_2sides_2up
{
   for file in $*
   do
      pr -e8 -f -n5 $file | lpr -J $file -P doc1 -K 2 -N 2
   done
}

function t
{
   export TERM=$1
   xs
}

function addpath
{
   PATH=$PATH:$1
   echo $PATH
}

function log
{
   echo `date '+%D %H:%M'` >> ~/.logfile
   echo "$*" >> ~/.logfile
   echo >> ~/.logfile
   date
}

function todo
{
   echo `date '+%D %H:%M'` >> ~/todo
   echo "$*" >> ~/todo
   echo >> ~/todo
}

function rot13
{
   tr [a-z][A-Z] [n-z][a-m][N-Z][A-M]
}


function unrot13
{
   tr [a-m][n-z][A-M][N-Z] [n-z][a-m][N-Z][A-M]
}


# Remove files that are a symbolic link to some other file, (eg. UnLink)

function UL
{
   for i in $*
   do
      if [ -L $i ]; then
         f=`ls -al $i | sed "s/^.*-> //"`
         rm -f $i
         cp $f $i
      fi
   done
}

#########################################################################
#
# Call the routines that I use each time that I login.
#
#########################################################################

# Main         # <--- Main

# Set the default directory and file protection mask.  By default, do
# not mask any protection on my ownership, but remove default write
# access for the group, and do not give "world" any default access.

export SHELL=/bin/bash
umask 022

OS=$(uname)
myterm=$(who am i)
myterm=$(echo $myterm | awk -F" " '{ print $2 }')
echo "The current HOST is $HOST"
echo "The current terminal is $myterm"
echo "The current shell is $SHELL"
echo "The terminal type is $TERM";echo "";echo ""
isLAT=$(echo $myterm | awk '{ print substr($0,1,3) }')

# The following condition checks to see if we are operating in a CDE
# "DT", that is, a CDE Desktop environment.  If we are, then we do not
# want to set terminal characteristics.  But if we are running a
# terminal emulator, such as dtterm, dxterm, or xterm, then we DO want
# to perform the following steps:

if [ ! "$DT" ]; then
     tty -s
#    if test $? = 0
#    then
#        stty
#    fi
#     tset -Q -I

     #
     # Define the default editing mode
     #

     set editing-mode emacs
     set show-all-if-ambiguous
fi

TheMasPoolTools
TheMasWebExports
TheMasPrinters
TheMasMisc
TheMasFileManagement
TheMasTerm
TheMasWorkon
TheMasHosts

return   # get out of any functions I may be in

# Finished .bashrc



_________________
Brian Masinick
Distros: SimplyMEPIS
sidux - no CAPS!, antiX, Debian
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
d_riordan
Member


Joined: 08 Jan 2024
Posts: 245
Location: Leominster, Massachusetts, U.S.A.

PostPosted: Fri Oct 12, 2024 5:53 am    Post subject: Re: Use them for directory navigation Reply with quote

masinick wrote:
You would only use these commands if, first of all, you are a frequent shell user (Bash, or equivalent shell that has these functions - I believe a couple shells do have pushd, popd, and dirs functions). Secondly, even if you are a shell user, you use them only if you create a hierarchy of directories and navigate through them a lot.


Maybe I'm starting to understand. It's begining to look like
Code:
$ cd

on steroids. Am I in the ballpark here? Probably a little less useful with TAB completion, I would assume.



_________________
*buntu 8.04
Back to top
View user's profile Send private message Visit poster's website
masinick
Linux Guru


Joined: 03 Apr 2024
Posts: 8615
Location: Concord, NH

PostPosted: Fri Oct 12, 2024 3:36 pm    Post subject: Re: Use them for directory navigation Reply with quote

d_riordan wrote:
masinick wrote:
You would only use these commands if, first of all, you are a frequent shell user (Bash, or equivalent shell that has these functions - I believe a couple shells do have pushd, popd, and dirs functions). Secondly, even if you are a shell user, you use them only if you create a hierarchy of directories and navigate through them a lot.


Maybe I'm starting to understand. It's begining to look like
Code:
$ cd

on steroids. Am I in the ballpark here? Probably a little less useful with TAB completion, I would assume.


The Bash implementation of cd is pretty rich. Tab completion makes directory handling pretty straightforward. Having a stack containing a list of all the directory entries that have been visited is useful. Korn Shell does have one substitution feature:

cd <old> <new> where you provide just the part of the path that you want to change, keeping the remainder of the path intact. I've not noticed that feature being implemented in Bash (though it may have snuck into the most recent versions post V3.0). With the stack feature in Bash, you can do without this feature. With the functions I provided, you have really powerful (steroid) feature directory movement with either Ksh or Bash.

Bottom line is that Ksh, Bash, and Zsh directory navigation is much more powerful than other implementations of the shell, though tcsh, a Csh derivative, has added many of these features and is the only C shell that is even remotely close to useful for anything more than routine interactive use. The POSIX based sh derived shells are MUCH better for writing scripts. I recommend avoiding C shell based shell scripts, including tcsh. Because Bash and tcsh do have so many interactive features in common, I don't even recommend using tcsh for any purpose other than routine work. Most Linux users stick with the Bash default, and I think that is a good thing.



_________________
Brian Masinick
Distros: SimplyMEPIS
sidux - no CAPS!, antiX, Debian
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
masinick
Linux Guru


Joined: 03 Apr 2024
Posts: 8615
Location: Concord, NH

PostPosted: Fri Oct 12, 2024 3:45 pm    Post subject: Korn and Bash differences and doc pointers Reply with quote

In Ksh, going back to my previous post, the Korn (ksh) shell does have a feature NOT found in Bash (and I have verified this by examining on line manuals for each. Here is the Korn shell feature not found in Bash:

Code:
cd [  -LP  ] [  arg   ]

Code:
cd [  -LP  ] old  new

Quote:
This command can be in either of two forms. In the first form it changes the current directory to arg. If arg is - the directory is changed to the previous directory. The shell variable HOME is the default arg. The variable PWD is set to the current directory. The shell variable CDPATH defines the search path for the directory containing arg. Alternative directory names are separated by a colon (Smile. The default path is <null> (specifying the current directory). Note that the current directory is specified by a null path name, which can appear immediately after the equal sign or between the colon delimiters anywhere else in the path list. If arg begins with a / then the search path is not used. Otherwise, each directory in the path is searched for arg.
The second form of cd substitutes the string new for the string old in the current directory name, PWD, and tries to change to this new directory.
By default, symbolic link names are treated literally when finding the directory name. This is equivalent to the -L option. The -P option causes symbolic links to be resolved when determining the directory. The last instance of -L or -P on the command line determines which method is used.


Taken from http://www.cs.princeton.edu/~jlk/kornshell/doc/man93.html

Korn Shell documentation can be found at http://www.kornshell.com/doc/

Bash Shell documentation can be found at http://www.gnu.org/software/bash/manual/bashref.html



_________________
Brian Masinick
Distros: SimplyMEPIS
sidux - no CAPS!, antiX, Debian
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
Display posts from previous:   
Post new topic   Reply to topic   printer-friendly view    USA Linux Users Group Forum Index » Command Line Commands All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
All content © 2024-2009 - Usa Linux Users Group
This forum is powered by phpBB. © 2024-2009 phpBB Group
Theme created by phpBBStyles.com and modified by Crouse