Sams Teach Yourself Shell Programming in 24 Hours
(Publisher: Macmillan Computer Publishing)
Author(s): Sriranga Veeraraghavan
ISBN: 0672314819
Publication Date: 01/01/99

Previous Table of Contents Next


mvdir.sh

The script mvdir.sh is given in Listing 22.1 (the line numbers are provided for your reference).

Listing 22.1 Complete Listing of the mvdir.sh Script

     1  #!/bin/sh
     2  # Name: mvdir
     3  # Desc: Move directories across file systems
     4  # Args: $1 -> src dir
     5  #       $2 -> dest dir
     6
     7  PATH=/bin:/usr/bin ; export PATH
     8
     9  # function to print errors and exit
    10
    11  printERROR() { echo "ERROR: $@." >&2 ; exit 1; }
    12
    13  # function to print usage message and exit
    14
    15  printUSAGE() { echo "USAGE: '/bin/basename $0' $@." >&2 ;
        ⇒exit 1; }
    16
    17  # check whether sufficient args are given
    18
    19  if [ $# -lt 2 ] ; then printUSAGE "[src] [dest]" ; fi
    20
    21  # check whether the source directory exists
    22
    23  if [ ! -d "$1" ] ; then
    24      printERROR "The source $1 is not a directory, or does
            ⇒not exist"
    25  fi
    26 
    27  # split up the source dir into its name and its parent's
    28  # name for easier processing later on
    29
    30  SRCDIR_PARENT="'/usr/bin/dirname $1'"
    31  SRCDIR_CHILD="'/bin/basename $1'"
    32
    33  # if dirname returns a relative dir we will be confused
    34  # after cd'ing later on. So reset it to the full path.
    35
    36  SRCDIR_PARENT="'(cd $SRCDIR_PARENT ; pwd ;)'"
    37
    38  # check whether the destination exits
    39
    40  if [ -d "$2" ] ; then
    41
    42      DESTDIR='( cd "$2" ; pwd ;)'
    43
    44  else
    45
    46      # if the destination doesn't exist then assume the
    47      # destination is the new name for the directory
    48
    49      DESTDIR="'/usr/bin/dirname $2'"
    50      NEWNAME="'/bin/basename $2'"
    51
    52      # if dirname returns a relative dir we will be confused
    53      # after cd'ing later on. So reset it to the full path.
    54
    55      DESTDIR='(cd $DESTDIR ; pwd ;)'
    56
    57      # if the parent of the destination doesn't exist,
    58      # we're in trouble. Tell the user and exit.
    59
    60      if [ ! -d "$DESTDIR" ] ; then
    61          printERROR "A parent of the destination directory
                ⇒$2 does not exist"
    62      fi
    63 
    64  fi
    65
    66  # try and cd to the parent src directory
    67
    68  cd "$SRCDIR_PARENT" > /dev/null 2>&1
    69  if [ $? -ne 0 ] ; then
    70      printERROR "Could not cd to $SRCDIR_PARENT"
    71  fi
    72
    73  # use tar to copy the source dir to the destination
    74
    75  /bin/tar -cpf - "$SRCDIR_CHILD" | ( cd "$DESTDIR" ;
        ⇒/bin/tar -xpf -)
    76
    77  if [ $? -ne 0 ] ; then
    78      printERROR "Unable to successfully move $1 to $2"
    79  fi
    80
    81  # if a rename of the copy is requested
    82
    83  if [ -n "$NEWNAME" ] ; then
    84
    85      # try and change to the destination directory
    86
    87      cd "$DESTDIR" > /dev/null 2>&1
    88      if [ $? -ne 0 ] ; then
    89          printERROR "Could not cd to $DESTDIR"
    90      fi
    91 
    92      # try and rename the copy
    93
    94      /bin/mv "$SRCDIR_CHILD" "$NEWNAME" > /dev/null 2>&1
    95      if [ $? -ne 0 ] ; then
    96          printERROR "Could not rename $1 to $2"
    97      fi
    98
    99      # return to the original directory
   100
   101      cd "$SRCDIR_PARENT" > /dev/null 2>&1
   102      if [ $? -ne 0 ] ; then
   103          printERROR "Could not cd to $SRCDIR_PARENT"
   104      fi
   105  fi
   106
   107  # try and remove the original
   108
   109  if [ -d "$SRCDIR_CHILD" ] ; then
   110      /bin/rm -r "$SRCDIR_CHILD" > /dev/null 2>&1
   111      if [ $? -ne 0 ] ; then
   112          printERROR "Could not remove $1"
   113      fi
   114  fi
   115
   116  exit 0

A Walkthrough of mvdir.sh

I’ll walk through the script and highlight some of the important points.

The first thing this script does is set the PATH variable (line 7). You do this to ensure that all the commands you use come from one of the two directories that you specified. When you write a script that can be run by many users, you have to take into account that some users might have modified their PATH such that the commands you are using are inaccessible or replaced by other versions. By setting the PATH variable explicitly, you avoid this problem.

Next the script defines a few utility functions (lines 11 and 15) used to print error usage messages. You can easily modify the script to replace these functions with the versions I gave you in Chapter 21.

After this the script validates its arguments as follows:

  It makes sure at least two arguments corresponding to source and destination directories are given (line 19).
  It makes sure the source is a directory (lines 23–25).

If at least two arguments are not given, you cannot be sure what the user wanted to move. Thus a usage message is printed and the script exits. If the source is not a directory or doesn’t exist, there is nothing to move, thus the script prints an error message and exits.

The next two lines (lines 30 and 31) are used to access the different parts of the pathname for the source. If the user specifies a directory as follows

$ mvdir.sh /tmp/mydir /home/ranga

there are two pieces of information you need:

  The name of the directory that the user wants moved, in this case mydir. This value is stored in the variable SRCDIR_CHILD (line 31).
  The name of the directory that this directory is located in, in this case /tmp. This value is stored in the variable SRCDIR_PARENT (line 30).

When you issue the mv or cp command, each performs this separation internally. Because this is a shell script, you have to do it explicitly using the dirname and basename commands.

One problem you run into is when the user specifies a relative path. When a cd command is used, the relative path required to access the source and destination directories changes; thus you need to determine the absolute path to the SRCDIR_PARENT. By using a subshell, you can make this determination in one line (line 36).


Previous Table of Contents Next