home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / osr5 / sco / scripts / nmv < prev    next >
Encoding:
Korn shell script  |  1997-08-26  |  5.5 KB  |  209 lines

  1. #!/bin/ksh
  2. # @(#) ncp.ksh,nmv.ksh 1.1 96/04/29
  3. # 92/01/18 john h. dubois iii (john@armory.com)
  4. # 92/01/31 added check for no args left after shifts
  5. # 92/02/17 added help
  6. # 92/02/25 remove path component from filename before tacking it onto dest.
  7. # 92/03/15 exec mv or cp
  8. # 93/07/13 Added -i
  9. # 93/09/29 Made abort if file exists optional.
  10. # 93/11/19 Exit before invoking mv if no files to move
  11. # 94/01/03 Added o option
  12. # 94/04/13 Added x option.
  13. #          Fixed appending of source filename, broken by earlier change.
  14. # 94/07/23 Append only the filename part of the source path.
  15. # 95/08/20 Split up overwrite? query.  Long filenames made it wrap, and when
  16. #          it did it exercised a bug in print -n.
  17. # 96/02/17 If Y is given interactively, be verbose about overwrites.
  18. # 96/04/29 Put filenames alone at end of error messages so they can be selected
  19.  
  20. alias !='test false ='
  21.  
  22. # interactive: Attempt to overwrite file should result in interactive
  23. # query rather than automatic failure.
  24. # noover: Do not overwrite files (if interactive is true, query, else fail)
  25. # overwrite: Only overwriting is allowed, not creation of new files.
  26. # debug: Print debugging info.
  27. typeset interactive=false noover=false overwrite=false debug=false
  28. typeset verboseOver=false
  29.  
  30. name=${0##*/}
  31.  
  32. case "$name" in
  33. ncp|nmv)
  34.     cmd=/bin/${name#?}
  35.     ;;
  36. *)
  37.     print -u2 "$name: Must be invoked as ncp or nmv."
  38.     exit 1
  39.     ;;
  40. esac
  41.  
  42. Usage="Usage: $name [-cfhio] $cmd-cmd-line"
  43.  
  44. while getopts :cfhiox opt; do
  45.     case $opt in
  46.     h)
  47.     echo \
  48. "$name: do a $cmd with extra checking and options.
  49. $Usage
  50. $name is used as a front end for $cmd to get the [icfo] options, and so
  51. that a trailing / will force the last component of the path to be
  52. interpreted as a directory, so that   $name foo bar/   will fail if bar is
  53. not an existing directory, instead of changing the name of foo to bar. 
  54. Effectively,  $name foo bar/   is short for  $name foo bar/foo
  55. Options: 
  56. -h prints this help.
  57. -c checks first for the existence of each file, and fails if it exists.
  58. -i is like -c except that if the file exists and stdin and stdout are a
  59.    tty, a query is printed and a reply is read; a file is overwritten only
  60.    if the reply begins with 'y'.
  61. -f unsets -c and -i (in case $cmd is aliased to $name).
  62. -o (overwrite only) checks that the named file(s) exist and fails for any
  63.    that do not.  It is the complement of the -c option.
  64. Whichever of [cifo] comes later on the command line determines the behaviour.
  65. Any of these options must come before any standard $cmd options."
  66.     exit 0
  67.     ;;
  68.     x)    
  69.     debug=true
  70.     ;;
  71.     c)    
  72.     noover=true
  73.     ;;
  74.     i)
  75.     noover=true
  76.     interactive=true
  77.     ;;
  78.     f)    
  79.     noover=false
  80.     interactive=false
  81.     ;;
  82.     o)    
  83.     overwrite=true
  84.     noover=false
  85.     interactive=false
  86.     ;;
  87.     +?)
  88.     echo "$name: options should not be preceded by a '+'."
  89.     exit 1
  90.     ;;
  91.     :) 
  92.     print -r -u2 -- \
  93.     "$name: Option '$OPTARG' requires a value.  Use -h for help."
  94.     exit 1
  95.     ;;
  96.     ?) 
  97.     echo "$name: $OPTARG: bad option.  Use -h for help."
  98.     exit 1
  99.     ;;
  100.     esac
  101. done
  102.  
  103. # remove args that were options
  104. let OPTIND=OPTIND-1
  105. shift $OPTIND
  106.  
  107. if [ $# -lt 2 ]; then
  108.     echo "$Usage\nUse -h for help."
  109.     exit
  110. fi
  111.  
  112. function Check {
  113.     if [ ! -f "$1" ] && $overwrite; then
  114.     print -- "$name: File does not exist: $1"
  115.     return 1
  116.     elif [ -f "$1" ]; then
  117.     if $noover; then
  118.         if ! $interactive || [ ! -t 0 -o ! -t 1 ]; then
  119.         print -- "$name: File exists: $1"
  120.         return 1
  121.         else
  122.         while :; do
  123.             print -u2 -n -r -- \
  124.     "$name: File exists: $1
  125.     Overwrite? (y)es/(n)o/(a)bort/(Y)es for all: "
  126.             read reply
  127.             set +x
  128.             case "$reply" in
  129.             y*)
  130.             print "$name: Overwriting file: $1"
  131.             return 0
  132.             ;;
  133.             Y*)
  134.             print "$name: Overwriting file: $1"
  135.             interactive=false
  136.             noover=false
  137.             verboseOver=true
  138.             return 0
  139.             ;;
  140.             [nN]*)
  141.             print "$name: Skipping file: $2"
  142.             return 1
  143.             ;;
  144.             [aA]*)
  145.             print "$name: Aborting."
  146.             exit 1
  147.             ;;
  148.             *)
  149.             print -u2 -- "$name: Invalid response."
  150.             ;;
  151.             esac
  152.         done
  153.         fi
  154.     else
  155.         $verboseOver && print "$name: Overwriting file: $1"
  156.         return 0
  157.     fi
  158.     else
  159.     return 0
  160.     fi
  161. }
  162.  
  163. # i is the index of the filename being examined
  164. # lastarg is the index of the last filename before the dest directory name
  165. typeset -i i=0 lastarg=$#-1
  166.  
  167. # Sets argv[0..$#-1]
  168. set -A argv -- "$@"
  169. dest=${argv[lastarg]}
  170.  
  171. if $debug; then
  172.     print -u2 \
  173. "interactive=$interactive noover=$noover overwrite=$overwrite debug=$debug
  174. lastarg=$lastarg dest=$dest name=$name cmd=$cmd
  175. files=$*"
  176. fi
  177.  
  178. if $noover || $overwrite; then
  179.     $debug && print -u2 "checking for existance of directories..."
  180.     # If the destination is not intended to be a directory...
  181.     if [ $# -eq 2 -a ! -d "$dest" ]; then
  182.     Check "$dest" "$1" || exit 0        # No files to copy
  183.     else
  184.     while [ i -lt lastarg ]; do
  185.         Check "$dest/${argv[i]##*/}" "${argv[i]}" || unset argv[i]
  186.         let i+=1
  187.     done
  188.     fi
  189. fi
  190.  
  191. [ ${#argv[@]} -lt 2 ] && exit 0
  192.  
  193. # If only 2 args are given, mv/cp will not insist that the destination
  194. # be a directory, which we want if the destination ends in "/" or if
  195. # the original number of args was >2.
  196. # $# is still the original number of args.
  197. # Tack the file name onto the destination to force this behaviour.
  198. if [[ ${#argv[@]} = 2 && ( "$2" = */ || $# -gt 2 ) ]]; then
  199.     $debug && print -u2 "Appending filename."
  200.     # Don't know which element of argv[] holds the source filename, 
  201.     # since may have started with more than 1 source file & had some unset.
  202.     # So, compact args to make it easy to find the set one.
  203.     set -A argv -- "${argv[@]}"
  204.     argv[1]="${argv[1]}/${argv[0]##*/}"
  205. fi
  206.  
  207. $debug && print -u2 "Executing command: $cmd ${argv[*]}"
  208. exec $cmd "${argv[@]}"
  209.