commit bash-20130301 snapshot

This commit is contained in:
Chet Ramey
2013-03-26 20:51:22 -04:00
parent 8eb22ee966
commit c7e43312f9
220 changed files with 45368 additions and 801 deletions
+59
View File
@@ -0,0 +1,59 @@
From spcecdt@armory.com Wed May 10 10:21:11 1995
Flags: 10
Return-Path: spcecdt@armory.com
Received: from po.cwru.edu (root@po.CWRU.Edu [129.22.4.2]) by odin.INS.CWRU.Edu with ESMTP (8.6.10+cwru/CWRU-2.1-ins)
id KAA22876; Wed, 10 May 1995 10:21:10 -0400 (from spcecdt@armory.com for <chet@odin.INS.CWRU.Edu>)
Received: from deepthought.armory.com (mmdf@deepthought.armory.com [192.122.209.42]) by po.cwru.edu with SMTP (8.6.10+cwru/CWRU-2.3)
id BAA16354; Wed, 10 May 1995 01:33:22 -0400 (from spcecdt@armory.com for <chet@po.cwru.edu>)
From: John DuBois <spcecdt@armory.com>
Date: Tue, 9 May 1995 22:33:12 -0700
In-Reply-To: Chet Ramey <chet@odin.ins.cwru.edu>
"ksh scripts" (May 9, 1:36pm)
X-Www: http://www.armory.com/~spcecdt/
X-Mailer: Mail User's Shell (7.2.5 10/14/92)
To: chet@po.cwru.edu
Subject: Re: ksh scripts
Message-ID: <9505092233.aa13001@deepthought.armory.com>
Sure. The canonical versions are available on ftp.armory.com; you might
want to pick up the latest versions before modifying them.
John
On May 9, 1:36pm, Chet Ramey wrote:
} Subject: ksh scripts
} From odin.ins.cwru.edu!chet Tue May 9 10:39:51 1995
} Received: from odin.INS.CWRU.Edu by deepthought.armory.com id aa22336;
} 9 May 95 10:39 PDT
} Received: (chet@localhost) by odin.INS.CWRU.Edu (8.6.10+cwru/CWRU-2.1-ins)
} id NAA20487; Tue, 9 May 1995 13:39:24 -0400 (from chet)
} Date: Tue, 9 May 1995 13:36:54 -0400
} From: Chet Ramey <chet@odin.ins.cwru.edu>
} To: john@armory.com
} Subject: ksh scripts
} Cc: chet@odin.ins.cwru.edu
} Reply-To: chet@po.cwru.edu
} Message-ID: <9505091736.AA20411.SM@odin.INS.CWRU.Edu>
} Read-Receipt-To: chet@po.CWRU.Edu
} MIME-Version: 1.0
} Content-Type: text/plain; charset=us-ascii
} Status: OR
}
} Hi. I'm the maintainer of bash (the GNU `Bourne Again shell') for
} the FSF.
}
} I picked up a tar file of ksh scripts you wrote from an anon FTP site
} a while back. I'd like your permission to include modified versions
} of some of them in the next major bash distribution (with proper credit
} given, of course). Is it OK if I do that?
}
} Chet Ramey
}
} --
} ``The lyf so short, the craft so long to lerne.'' - Chaucer
}
} Chet Ramey, Case Western Reserve University Internet: chet@po.CWRU.Edu
}-- End of excerpt from Chet Ramey
+37
View File
@@ -0,0 +1,37 @@
This collection of scripts was originally written for ksh-88 by
John DuBois <spcecdt@armory.com>. The conversion to bash v2
syntax was done by Chet Ramey.
These scripts are as-is; there is no copyright associated with
any of them. They exist simply as examples of bash scripting.
Here's a description of what's in this directory:
arc2tarz Convert an "arc" archive to a compressed tar archive.
cal2day.bash Convert a day number to a name.
corename Tell what produced a core file.
fman Fast man(1) replacement.
frcp Copy files using ftp(1) but with rcp-type command line syntax.
lowercase Change filenames to lower case.
ncp A nicer front end for cp(1) (has -i, etc.).
newext Change the extension of a group of files.
nmv A nicer front end for mv(1) (has -i, etc.).
pages Print specified pages from files.
PERMISSION Permissions to use the scripts in this directory.
pf A pager front end that handles compressed files.
README README
ren Rename files by changing parts of filenames that match a pattern.
rename Change the names of files that match a pattern.
repeat Execute a command multiple times.
untar Unarchive a (possibly compressed) tarfile into a directory.
uudec Carefully uudecode(1) multiple files.
uuenc uuencode(1) multiple files.
vtree Print a visual display of a directory tree.
where Show where commands that match a pattern are.
The following scripts were written or converted by Chet Ramey:
bashrand Random number generator with upper and lower bounds and optional seed.
cdhist.bash cd replacement with a directory stack added.
pmtop Poor man's 'top(1)' for SunOS 4.x and BSD/OS.
shprof Line profiler for bash scripts.
+85
View File
@@ -0,0 +1,85 @@
#! /bin/bash
#
# original from:
# arc2tarz: convert arced file to tarred, compressed form.
# @(#) arc2tarz.ksh 1.0 92/02/16
# 91/03/28 john h. dubois iii (john@armory.com)
# 92/02/16 added -h option for help
#
# conversion to bash v2 syntax by Chet Ramey
unset ENV
Usage="Usage: $0 arcfile [-hcg] [ tarzfile ]"
phelp()
{
echo "$Usage
arcfile is the name of an arc file to convert to tarred, compressed form.
The file must have a .arc extension, but only the base name needs to be
given. If no output file name is given, it will be created in the current
directory with the name being the arcfile basename followed by .tar.EXT.
If the -c option is given, compress will be used, and EXT will be Z.
The default (also available with -g) is to use gzip, in which case EXT
is gz. If the basename is too long the extension may be truncated. All
uppercase letters in the names of files in the archive are moved to lowercase."
}
compress=gzip
ext=gz
while getopts "hcg" opt; do
case "$opt" in
h) phelp; exit 0;;
c) compress=compress; ext=Z;;
g) compress=gzip ; ext=gz ;;
*) echo "$Usage" 1>&2 ; exit 2;;
esac
done
shift $((OPTIND - 1))
if [ $# = 0 ]; then
phelp
exit 0
fi
[ -z "$TMP" ] && tmpdir=/tmp/arc2tarz.$$ || tmpdir=$TMP/arc2tarz.$$
case "$1" in
*.arc) arcfile=$1 ;;
*) arcfile=$1.arc ;;
esac
if [ ! -f $arcfile ] || [ ! -r $arcfile ]; then
echo "Could not open arc file \"$arcfile\"."
exit 1
fi
case "$arcfile" in
/*) ;;
*) arcfile=$PWD/$arcfile ;;
esac
basename=${arcfile%.arc}
basename=${basename##*/}
[ $# -lt 2 ] && tarzname=$PWD/$basename.tar.$ext || tarzname=$2
trap 'rm -rf $tmpdir $tarzname' 1 2 3 6 15
mkdir $tmpdir
cd $tmpdir
echo "unarcing files..."
arc -ie $arcfile
# lowercase
for f in *; do
new=$(echo $f | tr A-Z a-z)
if [ "$f" != "$new" ]; then
mv $f $new
fi
done
echo "tarring/compressing files..."
tar cf - * | $compress > $tarzname
cd -
rm -rf $tmpdir
+76
View File
@@ -0,0 +1,76 @@
#! /bin/bash
# bashrand - generate a random number in a specified range with an
# optionally specified ``seed'' value.
#
# Original Author: Peter Turnbull, May 1993
usage()
{
echo "$PROG: usage: $PROG [-s seed] lower-limit upper-limit" >&2
}
PROG=${0##*/}
SEED=$$ # Initialize random-number seed value with PID
while getopts s: opt
do
case "$opt" in
s) SEED=$OPTARG ;;
*) usage ; exit 2 ;;
esac
done
shift $((OPTIND - 1))
# Process command-line arguments:
case $# in
2) Lower=$1; Upper=$2 ;;
*) usage ; exit 2 ;;
esac
# Check that specified values are integers:
expr "$Lower" + 0 >/dev/null 2>&1 || {
echo "$PROG: lower ($Lower) not an integer" >&2
exit 1
}
expr "$Upper" + 0 >/dev/null 2>&1 || {
echo "$PROG: upper ($Upper) not an integer" >&2
exit 1
}
expr "$SEED" + 0 >/dev/null 2>&1 || {
echo "$PROG: seed ($SEED) not an integer" >&2
exit 1
}
# Check that values are in the correct range:
(( $Lower < 0 )) || [ `expr "$Lower" : '.*'` -gt 5 ] && {
echo "$PROG: Lower limit ($Lower) out of range" >&2
exit 1
}
(( $Upper > 32767 )) || [ `expr "$Upper" : '.*'` -gt 5 ] && {
echo "$PROG: Upper limit ($Upper) out of range" >&2;
exit 1
}
(( $SEED < 0 )) || (( $SEED > 32767 )) || [ `expr "$SEED" : '.*'` -gt 5 ] && {
echo "$PROG: Seed value ($SEED) out of range (0 to 32767)" >&2
exit 1
}
(( $Upper <= $Lower )) && {
echo "$PROG: upper ($Upper) <= lower value ($Lower)" >&2
exit 1
}
# Seed the random-number generator:
RANDOM=$SEED
# Compute value, scaled within range:
let rand="$RANDOM % ($Upper - $Lower + 1) + $Lower"
# Report result:
echo $rand
+49
View File
@@ -0,0 +1,49 @@
#!/bin/bash
# cal2day - "parse" appropriate calendar output to match date number
# with day name.
#
# usage: cal2day month day [year]
#
# ORIGINAL *TAG:33239 3:Dec 9 1997:0755:sh.d/cal2day:
#
# Obtained from usenet
#
# Converted to bash v2 syntax by Chet Ramey <chet@po.cwru.edu>
#1 PARSE OPTIONS
while getopts :dls _inst
do case $_inst in
(d) format='%1d%.0s\n' ;; # 0, 1, ..., 7
(l) format='%0.s%-s\n' ;; # Sunday, Monday, ..., Saturday
(s) format='%0.s%-.3s\n' ;; # Sun, Mon, ..., Sat
esac
done
shift $((OPTIND-1))
#2 PARAMETER VALUES
((!$#)) && set -- $(date '+%m %d')
: ${format:='%0.s%-.3s\n'}
: ${1:?missing month parameter [1-12]}
: ${2:?missing day parameter [1-31]}
#3 CALCULATE DAY-OF-WEEK FROM DATE
cal $1 ${3:-$(date +%Y)} | gawk -FX '
BEGIN { day="Sunday Monday Tuesday WednesdayThursday Friday Saturday"
sub(/^0/, "", daynum)
dayre="(^| )" daynum "( |$)"
}
#NR==2 { print length($0) }
NR==1 || NR==2 \
{ next }
dayre { if (match($0, dayre))
{ #print RSTART, RLENGTH, substr($0, RSTART, RLENGTH)
if (daynum<=9 || RSTART==1) RSTART-=1
exit
}
}
END { # 20/21 char width assumed
printf format, RSTART/3, substr(day, RSTART*3+1, 9)
}
' daynum=$2 format=$format -
exit 0
+176
View File
@@ -0,0 +1,176 @@
#! /bin/bash
#
# cdhist - cd replacement with a directory stack like pushd/popd
#
# usage: cd [-l] [-n] [-] [dir]
#
# options:
# -l print the cd directory stack, one entry per line
# - equivalent to $OLDPWD
# -n cd to nth directory in cd directory stack
# -s cd to first directory in stack matching (substring) `s'
#
# arguments:
# dir cd to dir and push dir onto the cd directory stack
#
# If the new directory is a directory in the stack and the options selected
# it (-n, -s), the new working directory is printed
#
# If the variable CDHISTFILE is set, the cd directory stack is loaded from
# and written to $CDHISTFILE every time `cd' is executed.
#
# Note: I got this off the net somewhere; I don't know the original author
#
# Chet Ramey
# chet@po.cwru.edu
_cd_print()
{
echo -e "$@"
}
cd()
{
typeset -i cdlen i
typeset t
if [ $# -eq 0 ]
then
set -- $HOME
fi
if [ "$CDHISTFILE" ] && [ -r "$CDHISTFILE" ] # if directory history exists
then
typeset CDHIST
i=-1
while read -r t # read directory history file
do
CDHIST[i=i+1]=$t
done <$CDHISTFILE
fi
if [ "${CDHIST[0]}" != "$PWD" ] && [ -n "$PWD" ]
then
_cdins # insert $PWD into cd history
fi
cdlen=${#CDHIST[*]} # number of elements in history
case "$@" in
-) # cd to new dir
if [ "$OLDPWD" = "" ] && ((cdlen>1))
then
'_cdprint' ${CDHIST[1]}
builtin cd ${CDHIST[1]}
pwd
else
builtin cd "$@"
# pwd
fi
;;
-l) # _cdprint directory list
((i=cdlen))
while (((i=i-1)>=0))
do
num=$i
'_cdprint' "$num ${CDHIST[i]}"
done
return
;;
-[0-9]|-[0-9][0-9]) # cd to dir in list
if (((i=${1#-})<cdlen))
then
'_cdprint' ${CDHIST[i]}
builtin cd ${CDHIST[i]}
pwd
else
builtin cd $@
# pwd
fi
;;
-*) # cd to matched dir in list
t=${1#-}
i=1
while ((i<cdlen))
do
case ${CDHIST[i]} in
*$t*)
'_cdprint' ${CDHIST[i]}
builtin cd ${CDHIST[i]}
pwd
break
;;
esac
((i=i+1))
done
if ((i>=cdlen))
then
builtin cd $@
# pwd
fi
;;
*) # cd to new dir
builtin cd $@
# pwd
;;
esac
_cdins # insert $PWD into cd history
if [ "$CDHISTFILE" ]
then
cdlen=${#CDHIST[*]} # number of elements in history
i=0
while ((i<cdlen))
do
echo ${CDHIST[i]} # update directory history
((i=i+1))
done >$CDHISTFILE
fi
}
_cdins() # insert $PWD into cd history
{ # meant to be called only by cd
typeset -i i
i=0
while (( i < ${#CDHIST[*]} )) # see if dir is already in list
do
if [ "${CDHIST[$i]}" = "$PWD" ]
then
break
fi
((i=i+1))
done
if (( i>22 )) # limit max size of list
then
i=22
fi
while (((i=i-1)>=0)) # bump old dirs in list
do
CDHIST[i+1]=${CDHIST[i]}
done
CDHIST[0]=$PWD # insert new directory in list
}
# examples
shopt -s expand_aliases
# go to known place before doing anything
cd /
echo CDHIST: "${CDHIST[@]}"
for dir in /tmp /bin - -2 -l
do
cd $dir
echo CDHIST: "${CDHIST[@]}"
echo PWD: $PWD
done
exit 0
+43
View File
@@ -0,0 +1,43 @@
#! /bin/bash
#
# original from:
# @(#) corename.ksh 1.0 93/04/01
# 92/11/11 john h. dubois iii (john@armory.com)
# 92/02/16 Added help option.
# 92/02/22 Added cd to origdir to fix prob w/multiple relative paths.
# 93/04/01 Added check for whether file exists.
#
# conversion to bash v2 syntax done by Chet Ramey
# inspired by belal's equivalent utility
if [ "$1" = -h ]; then
echo \
"$0: print the names of executables that dumped core.
Usage: $0 [corename ...]
If no corename is given, \"core\" is assumed."
exit 0
fi
[ $# = 0 ] && set core
origdir=$PWD
for i; do
cd $origdir
file=${i##*/}
dir=${i%$file}
[ -z "$dir" ] && dir=$origdir/
if [ ! -f $dir$file ]; then
echo "$dir$file: No such file."
continue
fi
if [ ! -r $dir$file ]; then
echo "$dir$file: Cannot open."
continue
fi
cd $dir
# the adb output syntax is highly variable. this works on SunOS 4.x
set -- $(adb $file < /dev/null 2>&1 | sed 1q)
name=${7#??}
echo "$i: ${name%??}"
done
+281
View File
@@ -0,0 +1,281 @@
#! /bin/bash
#
# original from:
# fman: new man program
# @(#) fman.ksh 1.5 94/04/16
# 91/07/03 john h. dubois iii (john@armory.com)
# 91/07/11 made it unpack man pages if neccessary
# 91/07/16 fixed test for whether man file pattern was expanded
# 92/01/21 made it read /etc/default/man to get section order,
# and only display the first section found.
# 92/02/06 changed name to fman
# 92/02/07 fixed bug in notfound
# 92/02/13 incorporated changes from DOS version
# 92/03/11 changed to use MANPATH from environment if set,
# and search all directories given in MANPATH
# 92/03/15 exec pager or man w/o forking
# 92/05/31 try using index if one exists
# 92/10/01 Added "See also <other sections>"
# 92/10/18 If PAGER is less, search for name of man page to make it easier
# to find information in man pages for multiple items
# 92/11/11 Make it work for compressed files not listed in index;
# deal with man pages listed in index that don't exist.
# 93/03/30 Fixed bug in MANPATH processing
# 93/06/17 Include paths in "See also:" message if they would be needed
# to get to a man page. Allow MANPATH spec on command line.
# 93/07/09 Added -h and -e options.
# 94/04/16 Added x option.
#
# conversion to bash v2 syntax done by Chet Ramey
istrue()
{
test 0 -ne "$1"
}
isfalse()
{
test 0 -eq "$1"
}
# Finds all sections that man page $1 is in and puts them in the the
# global array Sections[].
# The filename of each page is put in FileNames[] with the same index.
# Global vars used:
# patharr[] MANPATH directories.
FindSectionsInIndex ()
{
typeset index indexes section mpath page=$1
typeset -i i=0 NIndex=0
for mpath in "${patharr[@]}"; do
if [ -r $mpath/index ]; then
indexes="$indexes $mpath/index"
let NIndex+=1
fi
done
[ -z "$indexes" ] && return
# Make grep give filename
[ NIndex -lt 2 ] && indexes="$indexes /dev/null"
# set positional parameters to
# indexfile:searchname pagename section ...
# e.g.
# /usr/man/index:FP_OFF Routines DOS
set -- `grep "^$page[ ]" $indexes`
while [ $# -gt 2 ]; do
FileNames[i]=${1%%index*}cat$3/$2.$3
Sections[i]=$3
shift 3
let i+=1
done
}
# Finds all sections that man page $1 is in by searching each man directory
# in the order given in patharr[],
# and puts them in the the global array Sections[].
# The filename of each page is put in FileNames[] with the same index.
# Global vars used:
# patharr[] MANPATH directories.
FindSectionsInDirs ()
{
local page=$1 mpath AllPaths Path
typeset -i i
for mpath in "${patharr[@]}"; do
AllPaths="$AllPaths $mpath/cat[0-9]*/$page.* $mpath/man[0-9]*/$page.*"
done
i=0
for Path in $AllPaths; do
istrue $debug && echo Path = $Path
case "$Path" in
*\*) ;;
*)
# Remove compressed-file suffix to make FileNames be the same
# as it is when built by FindSectionsInIndex()
FileNames[i]=${Path%.[zZ]}
Path=${Path%/*}
Sections[i]=${Path##*/*.}
let i+=1 ;;
esac
done
}
# FindSection: display man page.
# Uses ordarr[] (built from $ORDER) to display the version of the man
# page that occurs first in $ORDER.
# Sections[] gives the sections that a man page was found in.
# If the global variable "exist" is set to 1, nothing is displayed;
# the function instead returns zero if a page is found, nonzero if not.
# The filename of each page is in FileNames[] with the same index.
# Global vars used:
# Sections[], FileNames[], ordarr[]
FindSection ()
{
typeset -i NumPages i foundsec
local section OtherSec filename NPAGER=$PAGER POpt page=$1 Pat
local PageFile
NumPages=${#Sections[*]} # Number of versions of man page found.
isfalse $NumPages && return 1
case "$PAGER" in
*less) Popt="-p$page" ;;
esac
# For each section in ORDER, determine if any man page was found in
# that section
for section in "${ordarr[@]}"; do
i=0
foundsec=0
while [ $i -lt $NumPages ]; do
if [ "${Sections[i]}" = $section ]; then
# Found a man page from this section of ORDER
filename=${FileNames[i]}
if [ -z "$PageFile" ]; then
PageFile=$filename
else
if istrue $foundsec; then
OtherSec="$OtherSec$page(${filename%/*/*} $section) "
else
OtherSec="$OtherSec$page($section) "
fi
fi
foundsec=1
istrue $exist && return
fi
let i+=1
done
done
# No pages with the specified section found.
[ -z "$PageFile" ] && return 1
# Return if all we want to know is whether the man page exists.
[ "$exist" = 1 ] && return 0
if [ -z "$OtherSec" ]; then
NPAGER="exec $PAGER"
fi
if [ -r $PageFile ]; then
$NPAGER $POpt $PageFile
elif [ -r $PageFile.z ]; then
pcat $PageFile.z | $NPAGER $POpt
elif [ -r $PageFile.Z ]; then
zcat $PageFile.Z | $NPAGER $POpt
elif [ -f $PageFile.gz ]; then
gzip -dc $PageFile.gz | $NPAGER $POpt
else
echo "$PageFile: cannot open." 1>&2
OtherSec=
unset Sections[i]
let i+=1
continue
fi
echo "See also $OtherSec"
exit 0
}
phelp()
{
echo "$name: print man pages.
$name locates and prints the specified manual pages from the online UNIX
documentation.
$Usage
Options:
-e: Determine whether the specified man page exists. Nothing is printed;
$0 exits with a zero status if the page exists and a nonzero status if
it does not.
-h: Print this help."
}
# main program
typeset -i exist=0 debug=0
name=${0##*/}
Usage="Usage: $name [-eh] [[manpath] section] command-name"
while getopts :hex opt; do
case $opt in
h) phelp; exit 0;;
e) exist=1 ;;
x) debug=1 ;;
+?) echo "$name: options should not be preceded by a '+'." 1>&2; exit 2;;
?)
echo "$name: $OPTARG: bad option. Use -h for help." 1>&2 ; exit 2 ;;
esac
done
# remove args that were options
shift $((OPTIND-1))
if [ $# -lt 1 ]; then
echo -e "$Usage\nUse -h for help." 1>&2
exit
fi
P=$PAGER
O=1:n:l:6:8:2:3:4:5:7:p:o
T=$TERM
M=${MANPATH:-/usr/local/man:/usr/man}
[ -f /etc/default/man ] && . /etc/default/man
[ -n "$P" ] && PAGER=$P
[ -n "$O" ] && ORDER=$O
[ -n "$T" ] && TERM=$T
[ -n "$M" ] && MANPATH=$M
case $# in
0) echo "No man page specified." ; exit 1;;
1) page=$1;;
2) ORDER=$(echo $1 | tr a-z A-Z) ; page=$2;;
3) MANPATH=$1
[ -n "$2" ] && ORDER=$(echo $2 | tr a-z A-Z)
page=$3;;
*) echo "Too many arguments."; exit 1;;
esac
aargs=("$@")
[ ! -t 0 ] && PAGER=cat
OIFS=$IFS
IFS=:
patharr=($MANPATH)
i=0
for d in $MANPATH; do
for sec in $ORDER; do
ordarr[i]=$d/cat${sec}
let i+=1
ordarr[i]=$d/man${sec}
let i+=1
done
done
IFS=$OIFS
istrue $debug && echo patharr = "${patharr[@]}"
# if less or more is being used, remove multiple blank lines
export LESS="-s $LESS"
export MORE="-s $MORE"
# Try using index
FindSectionsInIndex "$page"
# Exit 0 if a page was found and we're just testing for existence.
FindSection "$page" && exit 0
# Try searching directories
unset Sections[*]
FindSectionsInDirs "$page"
FindSection "$page" && exit 0
istrue $exist && exit 1
# Try using man
# If using more or less, make man run faster by letting more or less compress
# multiple blank lines instead of rmb
#case "$PAGER" in
#*more|*less) manopt=-b;;
#esac
#cmd=(man $manopt -p$PAGER "${aargs[@]}")
export PAGER
cmd=(man $manopt "${aargs[@]}")
istrue $debug && echo "$name: running ${cmd[*]}" 1>&2
exec "${cmd[@]}"
+288
View File
@@ -0,0 +1,288 @@
#! /bin/bash
#
# original from:
#
# @(#) frcp.ksh 2.2 93/11/14
# 92/06/29 john h. dubois iii (john@armory.com)
# 92/10/14 Cleaned up, improved, added -d and -r options
# 92/11/11 Made work with a dest of '.'
# 93/07/09 Added -l and -n options, & login as anonymous if no .netrc entry
# 93/11/14 Use either passwd or password in .netrc, since ftp does.
#
# conversion to bash v2 syntax by Chet Ramey
#
# frcp: ftp front end with rcp-like syntax.
# Note: requires any machine names given to be listed with
# user and password in .netrc. If not, anonymous FTP is
# done.
#
# full path to ftp binary
if [ -x /usr/bin/ftp ]; then
FTP=/usr/bin/ftp;
elif [ -x /usr/ucb/ftp ]; then
FTP=/usr/ucb/ftp
else
FTP=ftp
fi
istrue()
{
test 0 -ne "$1"
}
isfalse()
{
test 0 -eq "$1"
}
# For each filename given, put the filename in filename[n]
# and the machine it is on in machine[n].
function SplitNames {
typeset file
typeset -i i=1
unset filename[*] machine[*]
for file; do
case "$file" in
*:*) machine[i]=${file%%:*} ;;
*) machine[i]=$LocalMach ;;
esac
filename[i]=${file#*:}
let i+=1
done
}
function verboseprint {
echo "$@"
echo "$@" 1>&2
}
function MakeDir {
OFS=$IFS
local IFS=/ dir component
case "$1" in
/*) ;;
*) dir=.
esac
set -- $1
IFS=$OFS
for component; do
dir=$dir/$component
if [ ! -d "$dir" ]; then
if mkdir "$dir"; then :; else
echo "Could not make directory $dir." >&2
return 1
fi
fi
done
return 0
}
lastisdot ()
{
case "$1" in
*/.|*/..) return 0;;
*) return 1;;
esac
}
# CopyFiles: issue ftp(TC) commands to copy files.
# Usage: CopyFiles [sourcemachine:]sourcepath ... [destmachine:]destpath
# Global vars:
# Uses LocalMach (should be name of local machine)
# Sets global arrs machine[]/filename[]
function CopyFiles {
unset machine[*] filename[*]
SplitNames "$@" # split names into filename[1..n] and machine[1..n]
local DestMach=${machine[$#]} # Machine to copy files to
local DestPath=${filename[$#]} # Destination file/dir
unset machine[$#] filename[$#]
[ -z "$DestPath" ] && DestPath=. # dest was given as machine:
# Try to determine if destination should be a directory
# so that it can be forced to be a directory.
case "$DestPath" in
*/) ;; # don't add / if trailing / already present
*) if [ $# -gt 2 ] || # if more than two args given, last must be a dir
# If dest in on local machine, check whether it is a directory
[ $DestMach = $LocalMach ] && [ -d "$DestPath" ] ||
# If dest ends with . or .., it is a directory
lastisdot "$DestPath"
then
DestPath=$DestPath/
fi ;;
esac
# If one of the above tests made us think dest is a directory,
# but it isn't, complain
case "$DestPath" in
*/) if [ "$DestMach" = "$LocalMach" ] && [ ! -d "$DestPath" ]; then
echo "Destination is not a directory." 1>&2
exit 1
fi ;;
esac
DoCopy "$DestMach" "$DestPath"
}
# Usage: OpenMachine machine-name
# Emits login sequence or doesn't, depending on .netrc file and global
# variables anon and noanon
OpenMachine ()
{
local machine=$1 netrc=$HOME/.netrc user= password=
if isfalse $anon && [ -r $netrc ]; then
set -- $(gawk '
/machine (.* )?'"$machine"'($| )/,/^ *$/ {
Fields[$1] = $2
if ("passwd" in Fields)
Fields["password"] = Fields["passwd"]
if ("login" in Fields && "password" in Fields) {
print Fields["login"] " " Fields["password"]
exit
}
}
' $netrc )
user=$1
password=$2
fi
if [ -z "$password" ]; then
if istrue $noanon; then
echo "No .netrc entry for machine $machine" 1>&2
exit 1
fi
user=anonymous
password=$USER@$LocalMach
fi
verboseprint open $machine
echo user $user "*******" 1>&2
echo user $user $password
}
# Usage: DoCopy destination-machine destination-path
# Copies the files in global arrs machine[]/filename[] to the given dest
# Global vars:
# Uses machine[], filename[], LocalMach, check
DoCopy ()
{
local DestMach=$1
local DestPath=$2
local OpenMach # Machine that connection is currently open to
local OWD=$PWD SourceMach SourceFile
local FileName
typeset -i i=1
while [ $i -le ${#machine[*]} ]; do
istrue $check && verboseprint "runique"
SourceMach=${machine[i]}
SourceFile=${filename[i]}
DestFile=$DestPath
# if DestPath is a dir,
# add source filename to it without source path
case "$DestFile" in
*/) DestFile=$DestFile${SourceFile##*/} ;;
esac
if [ $SourceMach = $LocalMach ]; then
if [ $DestMach != "$OpenMach" ]; then
OpenMachine $DestMach
OpenMach=$DestMach
fi
verboseprint put $SourceFile $DestFile
elif [ $DestMach = $LocalMach ]; then
if istrue $check && [ -f "$DestFile" ]; then
echo "$DestFile already exists." 1>&2
continue
fi
# If destination is on local machine,
# the dest will be a full dir/filename
if istrue $createdirs; then
MakeDir "${DestFile%/*}" || continue
fi
if [ $SourceMach != "$OpenMach" ]; then
OpenMachine $SourceMach
OpenMach=$SourceMach
fi
# If source filename has wildcards ([, ], *, ?) do an mget
case "$SourceFile" in
\[*\]|*\**|*\?*)
verboseprint lcd "$DestFile"
verboseprint mget "$SourceFile"
verboseprint lcd $OWD ;;
*) verboseprint get "$SourceFile" "$DestFile" ;;
esac
else
echo "Neither source machine \"$SourceMach\" "\
"nor destination machine \"$DestMach\" is local." 1>&2
fi
let i+=1
done
}
# Start of main program
name=${0##*/}
if [ "$1" = -h ]; then
echo \
"$name: do ftp transfers using rcp-style parameters.
Usage: $name <source> <destpath> or $name <source> [<source> ...] <destdir>
At least one of <source> and <destpath> must be the local system.
A remote filename is given as machinename:filename
If remote filenames contain wildcards, they will be globbed on the remote
machine. Make sure they are quoted when $name is invoked.
If the invoking user's .netrc file (see ftp(TC)) contains an entry for the
remote system with a login and password supplied, $name will log in using
the given login and password. If not, $name will login in as user
anonymous and with the user@localsystem as the password.
Options:
-c: check: do not overwrite files.
-d: create directories as needed.
-f: force: overwrite files (default).
-h: print this help.
-l: fail if there is no entry with login and password for the remote system,
instead of logging in as anonymous.
-n: log in as anonymous even if there is an entry for the remote system in
the user's .netrc file.
-r: read source/dest filename pairs from the standard input,
one pair per line, and copy files accordingly."
exit 0
fi
typeset -i check=0 createdirs=0 readinput=0 anon=0 noanon=0
while getopts :cdflnr Option
do
case "$Option" in
c) check=1;;
d) createdirs=1;;
f) check=0;;
l) noanon=1;;
n) anon=1;;
r) readinput=1;;
\?) echo "$OPTARG: invalid option."; exit 1;;
esac
done
shift $((OPTIND-1))
LocalMach=`hostname`
if istrue $readinput; then
while read line; do
CopyFiles $line
done | $FTP -nv
else
if [ $# -lt 2 ]; then
echo "$name: Not enough arguments. Use -h for help." 1>&2
exit
fi
CopyFiles "$@" | $FTP -nv
fi
+44
View File
@@ -0,0 +1,44 @@
#! /bin/bash
#
# original from
# @(#) lowercase.ksh 1.0 92/10/08
# 92/10/08 john h. dubois iii (john@armory.com)
#
# conversion to bash v2 syntax done by Chet Ramey
Usage="Usage: $name file ..."
phelp()
{
echo "$name: change filenames to lower case.
$Usage
Each file is moved to a name with the same directory component, if any,
and with a filename component that is the same as the original but with
any upper case letters changed to lower case."
}
name=${0##*/}
while getopts "h" opt; do
case "$opt" in
h) phelp; exit 0;;
*) echo "$Usage" 1>&2; exit 2;;
esac
done
shift $((OPTIND - 1))
for file; do
filename=${file##*/}
case "$file" in
*/*) dirname=${file%/*} ;;
*) dirname=. ;;
esac
nf=$(echo $filename | tr A-Z a-z)
newname="${dirname}/${nf}"
if [ "$nf" != "$filename" ]; then
mv "$file" "$newname"
echo "$0: $file -> $newname"
else
echo "$0: $file not changed."
fi
done
+187
View File
@@ -0,0 +1,187 @@
#! /bin/bash
#
# original from:
# @(#) ncp.ksh,nmv.ksh 1.1 94/07/23
# 92/01/18 john h. dubois iii (john@armory.com)
# 92/01/31 added check for no args left after shifts
# 92/02/17 added help
# 92/02/25 remove path component from filename before tacking it onto dest.
# 92/03/15 exec mv or cp
# 93/07/13 Added -i
# 93/09/29 Made abort if file exists optional.
# 93/11/19 Exit before invoking mv if no files to move
# 94/01/03 Added o option
# 94/04/13 Added x option.
# Fixed appending of source filename, broken by earlier change.
# 94/07/23 Append only the filename part of the source path.
#
# conversion to bash v2 syntax done by Chet Ramey
false()
{
return 1
}
true()
{
return 0
}
phelp()
{
echo "$name: do a $cmd with extra checking and options.
$Usage
$name is used as a front end for $cmd to get the [icfo] options, and so
that a trailing / will force the last component of the path to be
interpreted as a directory, so that $name foo bar/ will fail if bar is
not an existing directory, instead of changing the name of foo to bar.
Effectively, $name foo bar/ is short for $name foo bar/foo
Options:
-h prints this help.
-c checks first for the existence of each file, and fails if it exists.
-i is like -c except that if the file exists and stdin and stdout are a
tty, a query is printed and a reply is read; a file is overwritten only
if the reply begins with 'y'.
-f unsets -c and -i (in case $cmd is aliased to $name).
-o (overwrite only) checks that the named file(s) exist and fails for any
that do not. It is the complement of the -c option.
Whichever of [cifo] comes later on the command line determines the behaviour.
Any of these options must come before any standard $cmd options."
}
# interactive: Attempt to overwrite file should result in interactive
# query rather than automatic failure.
# noover: Do not overwrite files (if interactive is true, query, else fail)
# overwrite: Only overwriting is allowed, not creation of new files.
# debug: Print debugging info.
typeset interactive=false noover=false overwrite=false debug=false
name=${0##*/}
case "$name" in
ncp|nmv) cmd=/bin/${name#?} ;;
*) echo "$name: Must be invoked as ncp or nmv." 1>&2 ; exit 2;;
esac
Usage="Usage: $name [-cfhio] $cmd-cmd-line"
while getopts :cfhiox opt; do
case $opt in
h) phelp; exit 0;;
x) debug=true ;;
c) noover=true ;;
i) noover=true ; interactive=true ;;
f) noover=false ; interactive=false ;;
o) overwrite=true ; noover=false ; interactive=false;;
+?) echo "$name: options should not be preceded by a '+'." 1>&2; exit 2;;
?) echo "$name: $OPTARG: bad option. Use -h for help." 1>&2 ; exit 2;;
esac
done
# remove args that were options
shift $((OPTIND - 1))
if [ $# -lt 2 ]; then
echo -e "$Usage\nUse -h for help."
exit
fi
Check()
{
if [ ! -f "$1" ] && $overwrite; then
echo "$name: $1: File does not exist." 1>&2
return 1
elif [ -f "$1" ] && $noover; then
if [ $interactive = false ] || [ ! -t 0 ] || [ ! -t 1 ]; then
echo "$name: $1: File exists." 1>&2
return 1
else
while :; do
echo -n \
"$name: $1: File exists. Overwrite? (y)es/(n)o/(a)bort/(Y)es for all: " 1>&2
read reply
case "$reply" in
y*)
echo "$name: Overwriting $1."
return 0
;;
Y*)
echo "$name: Overwriting $1."
interactive=false
noover=false
return 0
;;
[nN]*)
echo "$name: Skipping $2."
return 1
;;
[aA]*)
echo "$name: Aborting."
exit 1
;;
*)
echo "$name: Invalid response." 1>&2
;;
esac
done
fi
else
return 0
fi
}
# i is the index of the filename being examined
# lastarg is the index of the last filename before the dest directory name
typeset -i i=0 lastarg=$(($#-1))
# Sets argv[0..$#-1]
argv=("$@")
$debug && echo argv = "${argv[@]}" 1>&2
dest=${argv[lastarg]}
if $debug; then
echo \
"interactive=$interactive noover=$noover overwrite=$overwrite debug=$debug
lastarg=$lastarg dest=$dest name=$name cmd=$cmd
files=$*" 1>&2
fi
if $noover || $overwrite; then
$debug && echo "checking for existance of directories..." 1>&2
# If the destination is not intended to be a directory...
if [ $# -eq 2 ] && [ ! -d "$dest" ]; then
Check "$dest" "$1" || exit 0 # No files to copy
else
while [ $i -lt $lastarg ]; do
Check "$dest/${argv[i]##*/}" "${argv[i]}" || unset argv[i]
let i+=1
done
fi
fi
[ ${#argv[@]} -lt 2 ] && exit 0
# If only 2 args are given, mv/cp will not insist that the destination
# be a directory, which we want if the destination ends in "/" or if
# the original number of args was >2.
# $# is still the original number of args.
# Tack the file name onto the destination to force this behaviour.
lastisslash()
{
case "$1" in
*/) return 0;;
*) return 1;;
esac
}
if [ ${#argv[@]} = 2 ] && { lastisslash "$2" || [ $# -gt 2 ]; }; then
$debug && echo "Appending filename." 1>&2
# Don't know which element of argv[] holds the source filename,
# since may have started with more than 1 source file & had some unset.
# So, compact args to make it easy to find the set one.
argv=("${argv[@]}")
argv[1]="${argv[1]}/${argv[0]##*/}"
fi
$debug && echo "Executing command: $cmd ${argv[@]}" 1>&2
exec $cmd "${argv[@]}"
+64
View File
@@ -0,0 +1,64 @@
#! /bin/bash
#
# original from:
# newext: change filename extension
# @(#) newext.sh 1.1 93/04/13
# 90/06/06 john h. dubois iii (john@armory.com)
# 90/11/14 changed ksh-specific code to hybrid: if running under Bourne,
# uses expr instead of ksh builtin ops. Removed SYSV specific code.
# 91/08/06 added -t option
# 92/11/06 made earlier code actually work!
# 93/04/13 If no filenames given, act on files in current dir
#
# conversion to bash v2 syntax by Chet Ramey
usage="Usage: newext [-th] <oldext> <newext> [filename ...]"
phelp()
{
echo "$usage
Rename all given files that end in oldext with newext replacing oldext.
If no filenames are given, all files in the current directory that end
in oldext are acted on (no filename is equivalent to '*').
Options:
-h: Print this help.
-t: Test: No action is taken except to print the mv commands that would
be executed if -t was not given."
}
while getopts "th" opt; do
case "$opt" in
t) echo=echo;;
h) phelp; exit 0;;
*) echo "$usage" 1>&2; exit 2;;
esac
done
shift $((OPTIND - 1))
oldext=$1
newext=$2
case $# in
[01]) echo -e "$usage\nUse -h for help." 1>&2; exit 2;;
2) shift ; shift; set -- *;;
*) shift ; shift;;
esac
found=
for file
do
case "$file" in
*$oldext)
newname="${file%$oldext}$newext"
$echo mv "$file" "$newname"
found=true;;
esac
done
if [ -z "$found" ]; then
echo "No files ending in \"$oldext\"."
exit 1
fi
exit 0
+187
View File
@@ -0,0 +1,187 @@
#! /bin/bash
#
# original from:
# @(#) ncp.ksh,nmv.ksh 1.1 94/07/23
# 92/01/18 john h. dubois iii (john@armory.com)
# 92/01/31 added check for no args left after shifts
# 92/02/17 added help
# 92/02/25 remove path component from filename before tacking it onto dest.
# 92/03/15 exec mv or cp
# 93/07/13 Added -i
# 93/09/29 Made abort if file exists optional.
# 93/11/19 Exit before invoking mv if no files to move
# 94/01/03 Added o option
# 94/04/13 Added x option.
# Fixed appending of source filename, broken by earlier change.
# 94/07/23 Append only the filename part of the source path.
#
# conversion to bash v2 syntax done by Chet Ramey
false()
{
return 1
}
true()
{
return 0
}
phelp()
{
echo "$name: do a $cmd with extra checking and options.
$Usage
$name is used as a front end for $cmd to get the [icfo] options, and so
that a trailing / will force the last component of the path to be
interpreted as a directory, so that $name foo bar/ will fail if bar is
not an existing directory, instead of changing the name of foo to bar.
Effectively, $name foo bar/ is short for $name foo bar/foo
Options:
-h prints this help.
-c checks first for the existence of each file, and fails if it exists.
-i is like -c except that if the file exists and stdin and stdout are a
tty, a query is printed and a reply is read; a file is overwritten only
if the reply begins with 'y'.
-f unsets -c and -i (in case $cmd is aliased to $name).
-o (overwrite only) checks that the named file(s) exist and fails for any
that do not. It is the complement of the -c option.
Whichever of [cifo] comes later on the command line determines the behaviour.
Any of these options must come before any standard $cmd options."
}
# interactive: Attempt to overwrite file should result in interactive
# query rather than automatic failure.
# noover: Do not overwrite files (if interactive is true, query, else fail)
# overwrite: Only overwriting is allowed, not creation of new files.
# debug: Print debugging info.
typeset interactive=false noover=false overwrite=false debug=false
name=${0##*/}
case "$name" in
ncp|nmv) cmd=/bin/${name#?} ;;
*) echo "$name: Must be invoked as ncp or nmv." 1>&2 ; exit 2;;
esac
Usage="Usage: $name [-cfhio] $cmd-cmd-line"
while getopts :cfhiox opt; do
case $opt in
h) phelp; exit 0;;
x) debug=true ;;
c) noover=true ;;
i) noover=true ; interactive=true ;;
f) noover=false ; interactive=false ;;
o) overwrite=true ; noover=false ; interactive=false;;
+?) echo "$name: options should not be preceded by a '+'." 1>&2; exit 2;;
?) echo "$name: $OPTARG: bad option. Use -h for help." 1>&2 ; exit 2;;
esac
done
# remove args that were options
shift $((OPTIND - 1))
if [ $# -lt 2 ]; then
echo -e "$Usage\nUse -h for help."
exit
fi
Check()
{
if [ ! -f "$1" ] && $overwrite; then
echo "$name: $1: File does not exist." 1>&2
return 1
elif [ -f "$1" ] && $noover; then
if [ $interactive = false ] || [ ! -t 0 ] || [ ! -t 1 ]; then
echo "$name: $1: File exists." 1>&2
return 1
else
while :; do
echo -n \
"$name: $1: File exists. Overwrite? (y)es/(n)o/(a)bort/(Y)es for all: " 1>&2
read reply
case "$reply" in
y*)
echo "$name: Overwriting $1."
return 0
;;
Y*)
echo "$name: Overwriting $1."
interactive=false
noover=false
return 0
;;
[nN]*)
echo "$name: Skipping $2."
return 1
;;
[aA]*)
echo "$name: Aborting."
exit 1
;;
*)
echo "$name: Invalid response." 1>&2
;;
esac
done
fi
else
return 0
fi
}
# i is the index of the filename being examined
# lastarg is the index of the last filename before the dest directory name
typeset -i i=0 lastarg=$(($#-1))
# Sets argv[0..$#-1]
argv=("$@")
$debug && echo argv = "${argv[@]}" 1>&2
dest=${argv[lastarg]}
if $debug; then
echo \
"interactive=$interactive noover=$noover overwrite=$overwrite debug=$debug
lastarg=$lastarg dest=$dest name=$name cmd=$cmd
files=$*" 1>&2
fi
if $noover || $overwrite; then
$debug && echo "checking for existance of directories..." 1>&2
# If the destination is not intended to be a directory...
if [ $# -eq 2 ] && [ ! -d "$dest" ]; then
Check "$dest" "$1" || exit 0 # No files to copy
else
while [ $i -lt $lastarg ]; do
Check "$dest/${argv[i]##*/}" "${argv[i]}" || unset argv[i]
let i+=1
done
fi
fi
[ ${#argv[@]} -lt 2 ] && exit 0
# If only 2 args are given, mv/cp will not insist that the destination
# be a directory, which we want if the destination ends in "/" or if
# the original number of args was >2.
# $# is still the original number of args.
# Tack the file name onto the destination to force this behaviour.
lastisslash()
{
case "$1" in
*/) return 0;;
*) return 1;;
esac
}
if [ ${#argv[@]} = 2 ] && { lastisslash "$2" || [ $# -gt 2 ]; }; then
$debug && echo "Appending filename." 1>&2
# Don't know which element of argv[] holds the source filename,
# since may have started with more than 1 source file & had some unset.
# So, compact args to make it easy to find the set one.
argv=("${argv[@]}")
argv[1]="${argv[1]}/${argv[0]##*/}"
fi
$debug && echo "Executing command: $cmd ${argv[@]}" 1>&2
exec $cmd "${argv[@]}"
+187
View File
@@ -0,0 +1,187 @@
#! /bin/bash
#
# original from:
# @(#) pages.sh 1.0 92/09/26
# 92/09/05 John H. DuBois III (jhdiii@armory.com)
# 92/09/26 Added help
#
# conversion to bash v2 syntax by Chet Ramey
Usage="$0 [-h] [-n lines/page] page-ranges [file ...]"
usage()
{
echo "$Usage" 1>&2
}
phelp()
{
echo "$0: print selected pages.
Usage: $Usage
If no file names are given, the standard input is read.
The input is grouped into pages and a selected subset of them is printed.
Formfeeds are acted on correctly.
If the output device does automatic line wrap, lines that longer than
the width of the output device will result in incorrect output.
The first non-option argument is a list of pages to print.
Pages are given as a list of ranges separated by commas.
A range is either one number, two numbers separted by a dash,
or one number followed by a dash. A range consisting of one
number followed by a dash extends to the end of the document.
Options:
-n sets the number of lines per page to n. The default is 66."
}
while getopts "n:h" opt; do
case "$opt" in
n) LinesPerPage=$OPTARG;;
h) phelp; exit 0;;
*) usage; exit 2;;
esac
done
shift $(($OPTIND - 1))
if [ $# -eq 0 ]; then
echo $0: no page ranges given. 1>&2
usage
exit 1
fi
PageList=$1
shift
gawk "
BEGIN {
PageList = \"$PageList\"; LinesPerPage = \"$LinesPerPage\""'
if (LinesPerPage == "")
LinesPerPage = 66
else
if (LinesPerPage !~ "[1-9][0-9]*")
ErrExit("Bad value for lines per page: " LinesPerPage)
LinesPerPage += 0
NumRanges = split(PageList,Ranges,",")
for (i = 1; i <= NumRanges; i++) {
if ((StartRange = EndRange = Ranges[i]) !~ "^[0-9]+(-([0-9]+)?)?$")
ErrExit("Bad range \"" StartRange "\"")
sub("-.*","",StartRange)
sub(".*-","",EndRange)
if (EndRange == "")
EndRange = 2 ^ 30
# Force StartRange and EndRange to be numeric values
if ((StartRange += 0) == 0 || (EndRange += 0) == 0)
ErrExit("Invalid page number \"0\" in range " Ranges[i])
if (StartRange > EndRange)
ErrExit("Start page comes after end page in range " Ranges[i])
TmpRangeStarts[i] = StartRange
TmpRangeEnds[i] = EndRange
}
# Sort ranges
qsort(TmpRangeStarts,k)
RangeEnds[0] = 0
for (i = 1; i <= NumRanges; i++) {
RangeEnds[i] = TmpRangeEnds[k[i]]
if ((RangeStarts[i] = TmpRangeStarts[k[i]]) <= RangeEnds[i - 1])
ErrExit("Overlapping ranges: " Ranges[k[i]] "," Ranges[k[i - 1]])
}
RangeNum = LineNum = PageNum = 1
InRange = In(PageNum,RangeStarts[RangeNum],RangeEnds[RangeNum])
FS = "\014"
}
{
if (LineNum > LinesPerPage)
NewPage()
if (InRange)
printf "%s",$1
# Deal with formfeeds
for (i = 2; i <= NF; i++) {
if (InRange)
printf "\014"
NewPage()
if (InRange)
printf "%s",$i
}
if (InRange)
print ""
LineNum++
}
function NewPage() {
PageNum++
LineNum = 1
# At the start of each page, check whether we are in a print range
WereInRange = InRange
InRange = In(PageNum,RangeStarts[RangeNum],RangeEnds[RangeNum])
# If last page was in range and we no longer are, move to next range
if (WereInRange && !InRange && ++RangeNum > NumRanges)
exit
}
function In(a,Min,Max) {
return (Min <= a && a <= Max)
}
function ErrExit(S) {
print S > "/dev/stderr"
Err = 1
exit 1
}
# Arr is an array of values with arbitrary indices.
# Array k is returned with numeric indices 1..n.
# The values in k are the indices of array arr,
# ordered so that if array arr is stepped through
# in the order arr[k[1]] .. arr[k[n]], it will be stepped
# through in order of the values of its elements.
# The return value is the number of elements in the array (n).
function qsort(arr,k, ArrInd,end) {
end = 0
for (ArrInd in arr)
k[++end] = ArrInd;
qsortseg(arr,k,1,end);
return end
}
function qsortseg(arr,k,start,end, left,right,sepval,tmp,tmpe,tmps) {
# handle two-element case explicitely for a tiny speedup
if ((end - start) == 1) {
if (arr[tmps = k[start]] > arr[tmpe = k[end]]) {
k[start] = tmpe
k[end] = tmps
}
return
}
left = start;
right = end;
sepval = arr[k[int((left + right) / 2)]]
# Make every element <= sepval be to the left of every element > sepval
while (left < right) {
while (arr[k[left]] < sepval)
left++
while (arr[k[right]] > sepval)
right--
if (left < right) {
tmp = k[left]
k[left++] = k[right]
k[right--] = tmp
}
}
if (left == right)
if (arr[k[left]] < sepval)
left++
else
right--
if (start < right)
qsortseg(arr,k,start,right)
if (left < end)
qsortseg(arr,k,left,end)
}
' "$@"
+127
View File
@@ -0,0 +1,127 @@
#! /bin/bash
#
# original from:
#
# @(#) p.ksh 1.1 93/11/09
# p: page compressed & plain files in the order given
# 92/01/23 john h. dubois iii (john@armory.com)
# 92/02/14 changed incorrect zpack to pcat
# 92/02/16 added help
# 92/10/11 search for file.Z and file.z if file not found
# 92/10/18 pass options to pager
# 93/11/09 Understand gzipped files too
# Wait after printing message about unreadable files
# Make less prompt include name of file being uncompressed
#
# conversion to bash v2 by Chet Ramey; renamed to pf
#
DefPager=/local/bin/less
istrue()
{
test 0 -ne "$1"
}
warn()
{
echo "$@" 1>&2
}
if [ "$1" = -h ]; then
echo \
"$0: page a file.
Usage: $0 [pager-option ...] [filename ...]
Files are paged by the program specified in the user's PAGER
environment variable, or by $DefPager if PAGER is not set.
If no filename is given, text to page is read from the standard input.
If filenames are given, they are either paged directly, or unpacked/
uncompressed and then paged. Files are assumed to be in packed, compressed,
or gzipped format if the filename ends in .Z, .z, or .gz respectively.
If a filename that does not end in .Z, .z, or .gz is not found, it is
searched for with one of those extensions attached.
Each group of plain files is paged by a single instance of the pager.
Each packed or compressed file is paged by a separate instance of the
pager.
Initial arguments beginning with + or - are taken to be pager options and
are passed to each instance of the pager.
If a pager option takes a value it should be given with the option as a
single argument (with no space between the option and the value)."
exit 0
fi
# Get pager options
while [ $# -gt 0 ]; do
case "$1" in
-*|+*) Opts="$Opts $1" ; shift;;
*) break;;
esac
done
[ -z "$PAGER" ] && PAGER=$DefPager
# Read from stdin
[ $# = 0 ] && exec $PAGER $Opts
typeset -i filenum=0 badfile=0
for file; do
if [ ! -r "$file" ]; then
case "$file" in
*.[Zz]|*.gz)
# Check if user specified a compressed file without giving its extension
for ext in Z z gz; do
if [ -r "$file.$ext" ]; then
file="$file.$ext"
break
fi
done;;
esac
fi
if [ ! -r "$file" ]; then
warn "$file: cannot read."
badfile=1
else
files[filenum]=$file
let filenum+=1
fi
done
if istrue $badfile && [ $filenum -gt 0 ]; then
echo -n "Press return to continue..." 1>&2
read
fi
unset plain
for file in "${files[@]}"; do
case "$file" in
*.[zZ]|*.gz)
set -- Z zcat z pcat gz gzcat
# Find correct uncompression program
while [ $# -gt 0 ]; do
case "$file" in
*.$1)
# Page any uncompressed files so that they will be read
# in the correct order
[ ${#plain[@]} -gt 0 ] && $PAGER $Opts "${plain[@]}"
unset plain[*]
# If page is less, set the prompt to include the name of
# the file being uncompressed. Escape the . in the extension
# because less treats is specially in prompts (other dots
# in filenames will still be mucked with).
case "$PAGER" in
*less) Prompt="-P[${file%.$1}\\.$1] (%pb\\%)" ;;
*) unset Prompt ;;
esac
$2 "$file" | $PAGER "$Prompt" $Opts
break
esac
shift 2
done
;;
*) plain[${#plain[@]}]=$file;;
esac
done
# Page any uncompressed files that haven't been paged yet
[ ${#plain[@]} -gt 0 ] && exec $PAGER $Opts "${plain[@]}"
+25
View File
@@ -0,0 +1,25 @@
#! /bin/bash
#
# pmtop - poor man's `top' for SunOS 4.x
#
CLEAR=clear # could also be 'tput clear'
HEADER="USER PID %CPU %MEM SZ RSS TT STAT START TIME COMMAND"
if [ -n "$LINES" ]; then
SS=$(( $LINES - 2 ))
else
SS=20
fi
while :
do
$CLEAR
echo "$HEADER"
ps -aux | sort -nr -k 3 | sed ${SS}q
sleep 5
done
exit 0
+585
View File
@@ -0,0 +1,585 @@
#!/bin/bash
#@ This program came from: ftp://ftp.armory.com/pub/scripts/ren
#@ Look there for the latest version.
#@ If you don't find it, look through http://www.armory.com/~ftp/
#
# @(#) ren 2.1.1 2002-03-17
# 1990-06-01 John H. DuBois III (john@armory.com)
# 1991-02-25 Improved help info
# 1992-06-07 Remove quotes from around shell pattern as required by new ksh
# 1994-05-10 Exit if no globbing chars given.
# 1995-01-23 Allow filename set to be given on command line.
# 1997-09-24 1.4 Let [] be used for globbing. Added x option.
# 1997-11-26 1.4.1 Notice if the sequences of globbing chars aren't the same.
# 1999-05-13 Changed name to ren to avoid conflict with /etc/rename
# 2000-01-01 1.4.2 Let input patterns that contain whitespace be used.
# 2001-02-14 1.5 Better test for whether old & new globbing seqs are identical.
# 2001-02-20 1.6 Added pP options.
# 2001-02-27 1.7 Added qf options. Improved interpretation of rename patterns.
# 2001-05-10 1.8 Allow multiple pP options. Added Qr options.
# 2001-07-25 2.0 Added mz options.
# 2001-11-25 2.1 Allow segment ranges to be given with -m. Work under ksh93.
# 2002-03-17 2.1.1 Fixed bug in test for legal expressions.
# todo: It would be nice to be able to escape metacharacters with '\'
# todo: Should enhance patterns to make ] in a pair of brackets work ([]])
# todo: Allow use of all ksh globbing patterns.
# todo: Allow use of extended regexps, with () to enumerate pieces and \num to
# todo: select them.
#
# Modifications for bash made by Chet Ramey <chet@po.cwru.edu>
name=${0##*/}
Usage="Usage:
$name [-fhqtv] [-m<segstart[:segend]=operation>] [-z<len>] [-[pP]<pattern>]
oldpattern [newpattern [filename ...]]
or
$name -r [same options as above] oldpattern newpattern directory ..."
tell=false
verbose=false
warn=true
warnNoFiles=true
debug=false
recurse=false
inclPat=
exclPat=
declare -i inclCt=0 exclCt=0
check=true
declare -i j op_end_seg
# Begin bash additions
shopt -s extglob
#
# ksh print emulation
#
# print [-Rnprsu[n]] [-f format] [arg ...]
#
# - end of options
# -R BSD-style -- only accept -n, no escapes
# -n do not add trailing newline
# -p no-op (no coprocesses)
# -r no escapes
# -s print to the history file
# -u n redirect output to fd n
# -f format printf "$format" "$@"
#
print()
{
local eflag=-e
local nflag= fflag= c
local fd=1
OPTIND=1
while getopts "fRnprsu:" c
do
case $c in
R) eflag= ;;
r) eflag= ;;
n) nflag=-n ;;
s) sflag=y ;;
f) fflag=y ;;
u) fd=$OPTARG ;;
p) ;;
esac
done
shift $(( $OPTIND - 1 ))
if [ -n "$fflag" ]; then
builtin printf "$@" >&$fd
return
fi
case "$sflag" in
y) builtin history -s "$*" ;;
*) builtin echo $eflag $nflag "$@" >&$fd
esac
}
# End bash additions
while getopts :htvxp:P:fqQrm:z: opt; do
case $opt in
h)
print -r -- \
"$name: rename files by changing parts of filenames that match a pattern.
$Usage
oldpattern and newpattern are subsets of sh filename patterns; the only
globbing operators (wildcards) allowed are ?, *, and []. All filenames that
match oldpattern will be renamed with the filename characters that match the
constant (non-globbing) characters of oldpattern changed to the corresponding
constant characters of newpattern. The characters of the filename that match
the globbing operators of oldpattern will be preserved. Globbing operators
in oldpattern must occur in the same order in newpattern; for every globbing
operators in newpattern there must be an identical globbing operators in
oldpattern in the same sequence. Both arguments should be quoted since
globbing operators are special to the shell. If filenames are given, only
those named are acted on; if not, all filenames that match oldpattern are acted
on. newpattern is required in all cases except when -m is given and no further
arguments are given.
If you are unsure whether a $name command will do what you intend, issue it
with the -t option first to be sure.
Examples:
$name \"/tmp/foo*.ba.?\" \"/tmp/new*x?\"
All filenames in /tmp that match foo*.ba.? will have the \"foo\" part
replaced by \"new\" and the \".ba.\" part replaced by \"x\".
For example, /tmp/fooblah.ba.baz would be renamed to /tmp/newblahxbaz.
$name \* \*- foo bar baz
foo, bar, and baz will be renamed to foo-, bar-, and baz-.
$name '????????' '????-??-??'
All filenames that are 8 characters long will be changed such that dashes
are inserted after the 4th and 6th characters.
Options:
-h: Print this help.
-r: Recursive operation. Filenames given on the command line after oldpattern
and newpattern are taken to be directories to traverse recursively. For
each subdirectory found, the specified renaming is applied to any matching
filenames. oldpattern and newpattern should not include any directory
components.
-p<pattern>, -P<pattern>: Act only on filenames that do (if -p is given) or do
not (if -P is given) match the sh-style filename globbing pattern
<pattern>. This further restricts the filenames that are acted on, beyond
the filename selection produced by oldpattern and the filename list (if
any). <pattern> must be quoted to prevent it from being interpreted by the
shell. Multiple instances of these options may be given. In this case,
filenames are acted on only if they match at least one of the patterns
given with -p and do not match any of the patterns given with -P.
-m<segstart[:segend]=operation>: For each file being renamed, perform a
mathematical operation on the string that results from concatenating
together the filename segments that matched globbing operator numbers
segstart through segend, where operators are numbered in order of
occurrence from the left. For example, in the pattern a?b*c[0-9]f, segment
1 consists of the character that matched ?, segment 2 consists of the
character(s) that matched *, and segment 3 consists of the character that
matched [0-9]. The selected segments are replaced with the result of the
mathematical operation.
The concatenated string must consist of characters that can be interpreted
as a decimal integer; if it does not, the filename is not acted on. This
number is assigned to the variable 'i', which can be referenced by the
operation. The operations available are those understood by the ksh
interpreter, which includes most of the operators and syntax of the C
language. The original filename segment is replaced by the result of the
operation. If -m is used, newpattern may be an empty string or not given
at all (if no directory/file names are given). In this case, it is taken
to be the same as oldpattern.
If segend is given, any fixed text that occurs in the pattern between the
starting and ending globbing segments is discarded. If there are fewer
globbing segments than segend, no complaint is issued; the string is formed
from segment segstart through the last segment that does exist.
If segend is not given, the only segment acted on is startseg.
Examples:
$name -m3=i+6 '??*.ppm'
This is equivalent to:
$name -m3=i+6 '??*.ppm' '??*.ppm'
Since the old pattern and new pattern are identical, this would
normally be a no-op. But in this case, if a filename of ab079.ppm is
given, it is changed to ab85.ppm.
$name '-m1:2=i*2' 'foo??bar'
This will change a file named foo12bar to foo24bar
$name '-m1:2=i*2' 'foo?xyz?bar'
This will also change a file named foo1xyz2bar to foo24bar
-z<len>: Set the size of the number fields that result when -m is used. The
field is truncated to the trailing <len> digits or filled out to <len>
digits with leading zeroes. In the above example, if -z3 is given, the
output filename will be ab085.ppm.
-f: Force rename. By default, $name will not rename files if a file with the
new filename already exists. If -f is given, $name will carry out the
rename anyway.
-q: Quiet operation. By default, if -f is given, $name will still notify the
user if a rename results in replacement of an already-existing filename.
If -q is given, no notification is issued.
-Q: Suppress other warnings. By default, a warning is issued if no files are
selected for acting upon. If -Q is given, no warning is issued.
-v: Show the rename commands being executed.
-t: Show what rename commands would be done, but do not carry them out."
exit 0
;;
f)
check=false
;;
q)
warn=false
;;
Q)
warnNoFiles=false
;;
r)
warnNoFiles=false
recurse=true
;;
t)
tell=true
;;
v)
verbose=true
;;
x)
verbose=true
debug=true
;;
p)
inclPats[inclCt]=$OPTARG
((inclCt+=1))
;;
P)
exclPats[exclCt]=$OPTARG
((exclCt+=1))
;;
m)
# Store operation for each segment number in ops[num]
# Store ending segment number in op_end_seg[num]
range=${OPTARG%%=*}
op=${OPTARG#*=}
start=${range%%:*}
end=${range#*:}
if [[ "$start" != +([0-9]) || "$start" -eq 0 ]]; then
print -ru2 -- "$name: Bad starting segment number given with -m: $start"
exit 1
fi
if [[ "$end" != +([0-9]) || "$end" -eq 0 ]]; then
print -ru2 -- "$name: Bad ending segment number given with -m: $end"
exit 1
fi
if [[ start -gt end ]]; then
print -ru2 -- "$name: Ending segment ($end) is less than starting segment ($start)"
exit 1
fi
if [[ "$op" != @(|*[!_a-zA-Z0-9])i@(|[!_a-zA-Z0-9]*) ]]; then
print -ru2 -- \
"$name: Operation given with -m does not reference 'i': $op"
exit 1
fi
# Test whether operation is legal. let returns 1 both for error
# indication and when last expression evaluates to 0, so evaluate 1
# after test expression.
i=1
let "$op" 1 2>/dev/null || {
print -ru2 -- \
"$name: Bad operation given with -m: $op"
exit 1
}
ops[start]=$op
op_end_seg[start]=$end
;;
z)
if [[ "$OPTARG" != +([0-9]) || "$OPTARG" -eq 0 ]]; then
print -ru2 -- "$name: Bad length given with -z: $OPTARG"
exit 1
fi
typeset -Z$OPTARG j || exit 1
;;
+?) # no way to tell getopts to not treat +x as an option
print -r -u2 "$name: Do not prefix options with '+'."
exit 1
;;
:)
print -r -u2 \
"$name: Option -$OPTARG requires a value.
$Usage
Use -h for help."
exit 1
;;
\?)
print -r -u2 \
"$name: -$OPTARG: no such option.
$Usage
Use -h for help."
exit 1
;;
esac
done
# remove args that were options
let OPTIND=OPTIND-1
shift $OPTIND
oldpat=$1
newpat=$2
# If -m is given, a non-existant or null newpat should be set to oldpat
if [ ${#ops[*]} -gt 0 ]; then
case $# in
0)
;;
1)
set -- "$oldpat" "$oldpat"
newpat=$oldpat
$debug && print -ru2 -- "Set new pattern to: $newpat"
;;
*)
if [ -z "$newpat" ]; then
shift 2
set -- "$oldpat" "$oldpat" "$@"
newpat=$oldpat
$debug && print -ru2 -- "Set new pattern to: $newpat"
fi
;;
esac
fi
# Make sure input patterns that contain whitespace can be expanded properly
IFS=
origPat=$oldpat
# Generate list of filenames to act on.
case $# in
[01])
print -u2 "$Usage\nUse -h for help."
exit 1
;;
2)
if $recurse; then
print -r -u2 "$name: No directory names given with -r. Use -h for help."
exit 1
fi
set -- $oldpat # Get list of all filenames that match 1st globbing pattern.
if [[ ! -a $1 ]]; then
$warnNoFiles && print -r -- "$name: No filenames match this pattern: $oldpat"
exit
fi
;;
*)
shift 2
;;
esac
integer patSegNum=1 numPatSegs
# For old ksh
# while [[ "$oldpat" = *'[\*\?]'* ]]; do
# Example oldpat: foo*.a
# Example newpat: bar*.b
# Build list of non-pattern segments and globbing segments found in arguments.
# Note the patterns given are used to get the list of filenames to act on,
# to delimit constant segments, and to determine which parts of filenames are
# to be replaced.
# Examples given for first iteration (in the example, the only iteration)
# The || newpat is to ensure that new pattern does not have more globbing
# segments than old pattern
while [[ "$oldpat" = *@([\*\?]|\[+([!\]])\])* ||
"$newpat" = *@([\*\?]|\[+([!\]])\])* ]]; do
## Get leftmost globbing pattern in oldpat
# Make r be oldpat with smallest left piece that includes a globbing
# pattern removed from it
r=${oldpat#*@([\*\?]|\[+([!\]])\])} # r=.a
# Make pat be oldpat with the above removed from it, leaving smallest
# left piece that includes a globbing pattern
pat=${oldpat%%"$r"} # pat=foo*
# Make l be pat with the globbing pattern removed from the right,
# leaving a constant string
l=${pat%@([\*\?]|\[+([!\]])\])} # l=foo
# Remove the constant part of pat from the left, leaving the globbing
# pattern
pat=${pat#"$l"} # pat=*
# Do the same thing for newpat, solely to provide a reliable test that
# both oldpat & newpat contain exactly the same sequence of globbing
# patterns.
r=${newpat#*@([\*\?]|\[+([!\]])\])} # r=.b
npat=${newpat%%"$r"} # pat=bar*
l=${npat%@([\*\?]|\[+([!\]])\])} # l=bar
npat=${npat#"$l"} # npat=*
if [[ "$pat" != "$npat" ]]; then
print -ru2 -- \
"$name: Old-pattern and new-pattern do not have the same sequence of globbing chars.
Pattern segment $patSegNum: Old pattern: $pat New pattern: $npat"
exit 1
fi
## Find parts before & after pattern
# oldpre[] stores the old constant part before the pattern,
# so that it can be removed and replaced with the new constant part.
oldpre[patSegNum]=${oldpat%%"$pat"*} # oldpre[1]=foo
# oldsuf stores the part that follows the globbing pattern,
# so that it too can be removed.
# After oldpre[] & oldsuf[] have been removed from a filename, what remains
# is the part matched by the globbing pattern, which is to be retained.
oldsuf[patSegNum]=${oldpat#*"$pat"} # oldsuf[1]=.a
# newpre[] stores the new constant part before the pattern,
# so that it can be used to replace the old constant part.
newpre[patSegNum]=${newpat%%"$pat"*} # newpre[1]=bar
# Get rid of processed part of patterns
oldpat=${oldpat#${oldpre[patSegNum]}"$pat"} # oldpat=.a
newpat=${newpat#${newpre[patSegNum]}"$pat"} # newpat=.b
# Store either * or ? in pats[], depending on whether this segment matches 1
# or any number of characters.
[[ "$pat" = \[* ]] && pat=?
pats[patSegNum]=$pat
((patSegNum+=1))
done
if [ patSegNum -eq 1 ]; then
print -u2 "No globbing chars in pattern."
exit 1
fi
oldpre[patSegNum]=${oldpat%%"$pat"*} # oldpre[2]=.a
oldsuf[patSegNum]=${oldpat#*"$pat"} # oldsuf[2]=.a
newpre[patSegNum]=${newpat%%"$pat"*} # newpre[2]=.b
numPatSegs=patSegNum
if $debug; then
patSegNum=1
while [[ patSegNum -le numPatSegs ]]; do
print -ru2 -- \
"Old prefix: <${oldpre[patSegNum]}> Old suffix: <${oldsuf[patSegNum]}> New prefix: <${newpre[patSegNum]}> Pattern: <${pats[patSegNum]}>"
((patSegNum+=1))
done
fi
# Example filename: foox.a
# Example oldpat: foo*.a
# Example newpat: bar*.b
integer numFiles=0
# Usage: renameFile filename [dirname]
# [dirname] is a directory name to prefix filenames with when they are printed
# for informational purposes.
# Uses globals:
# inclCt exclCt inclPats[] exclPats[] ops[]
# numPatSegs oldpre[] oldsuf[] newpre[] pats[]
# check warn tell verbose name
# Modifies globals: numFiles
function renameFile {
typeset file=$1 subdir=$2
integer patSegNum patnum
typeset origname porigname newfile matchtext pnewfile matchsegs
integer startseg endseg
origname=$file # origname=foox.a
porigname=$subdir$file
# Unfortunately, ksh88 does not do a good job of allowing for patterns
# stored in variables. Without the conditional expression being eval'ed,
# only sh patterns are recognized. If the expression is eval'ed, full
# ksh expressions can be used, but then expressions that contain whitespace
# break unless the user passed a pattern with the whitespace properly
# quoted, which is not intuititive. This is fixed in ksh93; full patterns
# work without being eval'ed.
if [ inclCt -gt 0 ]; then
patnum=0
while [ patnum -lt inclCt ]; do
[[ "$file" = ${inclPats[patnum]} ]] && break
((patnum+=1))
done
if [ patnum -eq inclCt ]; then
$debug && print -ru2 -- "Skipping not-included filename '$porigname'"
return 1
fi
fi
patnum=0
while [ patnum -lt exclCt ]; do
if [[ "$file" = ${exclPats[patnum]} ]]; then
$debug && print -ru2 -- "Skipping excluded filename '$porigname'"
return 1
fi
((patnum+=1))
done
# Extract matching segments from filename
((numFiles+=1))
patSegNum=1
while [[ patSegNum -le numPatSegs ]]; do
# Remove a fixed prefix iteration: 1 2
file=${file#${oldpre[patSegNum]}} # file=x.a file=
# Save the part of this suffix that is to be retained. To do this, we
# need to know what part of the suffix matched the current globbing
# segment. If the globbing segment is a *, this is done by removing
# the minimum part of the suffix that matches oldsuf (since * matches
# the longest segment possible). If the globbing segment is ? or []
# (the latter has already been coverted to ?), it is done by taking the
# next character.
if [ "${pats[patSegNum]}" == \? ]; then
matchtext=${file#?}
matchtext=${file%$matchtext}
else
matchtext=${file%${oldsuf[patSegNum]}} # matchtext=x matchtext=
fi
$debug && print -ru2 -- "Matching segment $patSegNum: $matchtext"
file=${file#$matchtext} # file=.a file=.a
matchsegs[patSegNum]=$matchtext
((patSegNum+=1))
done
# Paste fixed and matching segments together to form new filename.
patSegNum=0
newfile=
while [[ patSegNum -le numPatSegs ]]; do
matchtext=${matchsegs[patSegNum]}
startseg=patSegNum
if [ -n "${ops[startseg]}" ]; then
endseg=${op_end_seg[startseg]}
while [ patSegNum -lt endseg ]; do
((patSegNum+=1))
matchtext=$matchtext${matchsegs[patSegNum]}
done
if [[ "$matchtext" != +([-0-9]) ]]; then
print -ru2 -- \
"Segment(s) $startseg - $endseg ($matchtext) of file '$porigname' do not form an integer; skipping this file."
return 2
fi
i=$matchtext
let "j=${ops[startseg]}" || {
print -ru2 -- \
"Operation failed on segment(s) $startseg - $endseg ($matchtext) of file '$file'; skipping this file."
return 2
}
$debug && print -ru2 -- "Converted $matchtext to $j"
matchtext=$j
fi
newfile=$newfile${newpre[startseg]}$matchtext # newfile=barx newfile=barx.b
((patSegNum+=1))
done
pnewfile=$subdir$newfile
if $check && [ -e "$newfile" ]; then
$warn &&
print -ru2 -- "$name: Not renaming \"$porigname\"; destination filename \"$pnewfile\" already exists."
return 2
fi
if $tell; then
print -n -r -- "Would move: $porigname -> $pnewfile"
$warn && [ -e "$newfile" ] && print -n -r " (destination filename already exists; would replace it)"
print ""
else
if $verbose; then
print -n -r -- "Moving: $porigname -> $pnewfile"
$warn && [ -e "$newfile" ] && print -n -r -- " (replacing old destination filename \"$pnewfile\")"
print ""
elif $warn && [ -e "$newfile" ]; then
print -r -- "$name: Note: Replacing old file \"$pnewfile\""
fi
mv -f -- "$origname" "$newfile"
fi
}
if $recurse; then
oPWD=$PWD
find "$@" -depth -type d ! -name '*
*' -print | while read dir; do
cd -- "$oPWD"
if cd -- "$dir"; then
for file in $origPat; do
renameFile "$file" "$dir/"
done
else
print -ru2 -- "$name: Could not access directory '$dir' - skipped."
fi
done
else
for file; do
renameFile "$file"
done
fi
if [ numFiles -eq 0 ]; then
$warnNoFiles && print -ru2 -- \
"$name: All filenames were excluded by patterns given with -p or -P."
fi
+122
View File
@@ -0,0 +1,122 @@
#! /bin/bash
#
# original from:
# @(#) rename.ksh 1.1 94/05/10
# 90/06/01 John DuBois (spcecdt@armory.com)
# 91/02/25 Improved help info
# 92/06/07 remove quotes from around shell pattern as required by new ksh
# 94/05/10 Exit if no globbing chars given.
#
# conversion to bash v2 syntax by Chet Ramey
phelp()
{
echo "$usage
All files that match oldpattern will be renamed with the
filename components that match the constant parts of oldpattern
changed to the corresponding constant parts of newpattern.
The components of the filename that match variable parts of
oldpattern will be preserved. Variable parts in oldpattern
must occur in the same order in newpattern. Variables parts
can be '?' and '*'.
Example:
rename \"/tmp/foo*.ba.?\" \"/tmp/new*x?\"
All files in /tmp that match foo*.ba.? will have the \"foo\" part
replaced by \"new\" and the \".ba.\" part replaced by \"x\"."
}
usage="usage: $name [-htv] oldpattern newpattern"
name=${0##/}
while getopts "htv" opt; do
case "$opt" in
t) tell=true;;
v) verbose=true;;
h) phelp; exit 0;;
*) echo "$name: $usage" 1>&2; exit 2;;
esac
done
shift $((OPTIND - 1))
if [ $# -lt 2 ]; then
phelp
exit 2
fi
oldpat=$1
newpat=$2
set -- $1
if [ ! -e "$1" ]; then
echo "$name: no files match $oldpat."
exit 1
fi
typeset -i i=1 j
# Example oldpat: foo*.a
# Example newpat: bar*.b
# Examples given for first iteration (in the example, the only interation)
while :; do
case "$oldpat" in
*[\*\?]*) ;;
*) break;;
esac
# Get leftmost globbing pattern in oldpat
pat=${oldpat#*[\*\?]} # pat=.a
pat=${oldpat%%"$pat"} # pat=foo*
pat=${pat##*[!\?\*]} # pat=*
# Find parts before & after pattern
oldpre[i]=${oldpat%%"$pat"*} # oldpre[1]=foo
oldsuf[i]=${oldpat#*"$pat"} # oldsuf[1]=.a
newpre[i]=${newpat%%"$pat"*} # newpre[1]=bar
# Get rid of processed part of patterns
oldpat=${oldpat#${oldpre[i]}"$pat"} # oldpat=.a
newpat=${newpat#${newpre[i]}"$pat"} # newpat=.b
let i=i+1
done
if [ $i -eq 1 ]; then
echo "No globbing chars in pattern." 1>&2
exit 1
fi
oldpre[i]=${oldpat%%"$pat"*} # oldpre[2]=.a
oldsuf[i]=${oldpat#*"$pat"} # oldsuf[2]=.a
newpre[i]=${newpat%%"$pat"*} # newpre[2]=.b
if [ -n "$verbose" ]; then
j=1
while let "j < i"; do
echo \
"Old prefix: ${oldpre[j]} Old suffix: ${oldsuf[j]} New prefix: ${newpre[j]}"
let j=j+1
done
fi
# Example file: foox.a
for file; do
j=1
origname=$file # origname=foox.a
newfile=
while let "j <= i"; do
# Peel off a prefix interation 1 2
file=${file#${oldpre[j]}} # file=x.a file=
# Save the part of this prefix that is to be retained
const=${file%${oldsuf[j]}} # const=x const=
newfile=$newfile${newpre[j]}$const # newfile=barx newfile=barx.b
file=${file#$const} # file=.a file=.a
let j=j+1
done
if [ -n "$tell" ]; then
echo "Would move \"$origname\" to \"$newfile\"."
else
if [ -n "$verbose" ]; then
echo "Moving \"$origname\" to \"$newfile\"."
fi
mv $origname $newfile
fi
done
+121
View File
@@ -0,0 +1,121 @@
#! /bin/bash
#
# original from:
# repeat: repeat a command.
# @(#) repeat.ksh 1.1 93/06/03
# 90/05 john h. dubois iii (john@armory.com)
# 90/11 added help
# 93/06/03 Added s, h, p, and v options
#
# conversion to bash v2 syntax done by Chet Ramey
istrue()
{
test 0 -ne "$1"
}
isfalse()
{
test 0 -eq "$1"
}
phelp()
{
echo "$name: repeatedly execute a command line.
$Usage
commandline is executed once for each integer from startcount through endcount
inclusive. The default for startcount is 1 if a positive endcount or no
endcount is given, and -1 if a negative endcount is given. A count
parameter consisting of a single number is taken to be an endcount. If
only an endcount is given and it is positive, commandline is executed
endcount times. endcount may be less than startcount. If no endcount is
given (e.g. a count parameter of \"10-\"), commandline execution repeats
indefinitely with the iteration variable incrementing in a positive
direction. A count parameter of consisting of \"-\" will repeat
indefinitely starting with 1.
Note that quoting and variables in commandline are interpreted twice, once
when it is passed to the repeat command, and once when it is actually executed.
The iteration variable is \"count\". If \$count is used in commandline, make
sure it is quoted with ' or \.
Options:
-h: Print this help.
-p: Print value of iteration variable on stderr before each iteration.
-s <sec>: sleep for <sec> seconds after each iteration except the last.
-v: Print start and end values before beginning."
}
name=${0##*/}
Usage="Usage: repeat [-hpv] [-s <sec>] [[startcount]-][endcount] command [arg ...]"
typeset -i count=1 forever=0 sleep=0 print=0 verbose=0
while getopts :0123456789hpvs: opt; do
case $opt in
h) phelp; exit 0;;
s) sleep=$OPTARG || exit 1;;
p) print=1;;
v)verbose=1;;
[0-9]) break;;
+?) echo "$name: options should not be preceded by a '+'." 1>&2; exit 2;;
?) echo "$name: $OPTARG: bad option. Use -h for help." 1>&2; exit 2;;
esac
done
# remove args that were options
shift $((OPTIND-1))
if [ $# -lt 2 ]; then
echo -e "$Usage\nUse -h for help." 1>&2
exit 2
fi
case "$1" in
-[0-9]*-|[0-9]*-)
# Start value only
count=${1%-}
forever=1
end="-1";
;;
-[0-9]*-[0-9]*|[0-9]*-[0-9]*)
# Start and end value
s=${1%-}
end=${s##[0-9]*-}
count=${s%-$end}
;;
-[0-9]*|[0-9]*)
end=$1
case "$end" in
-\*) count=-1;;
esac
;;
-)
forever=1
end="-1";
;;
*)
echo "$name: bad count parameter: $1" 1>&2
exit 1
;;
esac
shift
[ -z "$end" ] && [ $count -le "$end" ] && increment=1 || increment=-1
istrue $verbose && echo "start=$count end=$end" 1>&2
# Need to do this here so that up to this point, -0 will keep the leading -
# and end will not be 0 if no value assigned
typeset -i end
let end+=increment # make loop inclusive of original endcount
while istrue $forever || [ $count -ne $end ]; do
istrue $print && echo $count 1>&2
eval "$@"
istrue $sleep && sleep $sleep
let count+=increment
done
+66
View File
@@ -0,0 +1,66 @@
#! /bin/bash
#
# shprof - a line profiler for shell scripts
#
# adapted from a similar program included in `The New KornShell' by
# Bolsky and Korn and posted to usenet by bsh20858@challenger.fhda.edu
#
# converted to bash v2 syntax by Chet Ramey
#
TMPFILE=${TMP:-/tmp}/shprof$$
trap 'rm -f $TMPFILE' EXIT
errexit()
{
echo $0: "$@" >&2
exit 1
}
# create script with profiling enabled
cat > $TMPFILE <<- \_EOF_
declare -a _line
_profend()
{
case "$1" in
/*|./*) file="$1" ;;
*) file=$(type -path "$1") ;;
esac
echo "*** line profile for $file ***"
i=1;
while read -r && [ $i -le $NLINE ]; do
count=${_line[$i]}
if [ "$count" -gt 0 ]; then
echo "[$count] $i: $REPLY"
fi
i=$((i + 1))
done <$file
_EOF_
# make the profiling script remove itself after printing line stats
echo "rm -f $TMPFILE" >> $TMPFILE
cat >> $TMPFILE <<- \_EOF_
}
_command=$1
shift
i=1
NLINE=$(wc -l < "$_command")
while [ $i -le $NLINE ]; do
_line[$i]=0
i=$((i + 1))
done
unset i
trap "_profend ${_command}" EXIT
trap '_line[$LINENO]=$((${_line[$LINENO]} + 1))' DEBUG
LINENO=0
_EOF_
case "$1" in
/*|./*) file=$1 ;;
*) file=$((type -path "$1")) ;;
esac
cat "${file-$1}" >> $TMPFILE || errexit "${1}: cannot open"
chmod +x $TMPFILE
exec -a "$file" $TMPFILE "$@"
+80
View File
@@ -0,0 +1,80 @@
#! /bin/bash
#
# original from:
# @(#) untar.ksh 1.0 93/11/10
# 92/10/08 john h. dubois iii (john@armory.com)
# 92/10/31 make it actually work if archive isn't in current dir!
# 93/11/10 Added pack and gzip archive support
#
# conversion to bash v2 syntax done by Chet Ramey
phelp()
{
echo \
"$name: extract tar archives into directories, uncompressing if neccessary.
Usage: $name archive[.tar[.[Z|gz]]] ..
If an archive name given does not end in .tar, .tar.Z, or .tar.gz, it is
searched for first with .tar added, then .tar.Z, and then .tar.gz added.
The real filename must end in either .tar, .tar.Z, or .tar.gz. A
directory with the name of the archive is created in the current directory
(not necessarily the directory that the archive is in) if it does not
exist, and the the contents of the archive are extracted into it.
Absolute pathnames in tarfiles are suppressed."
}
if [ $# -eq 0 ]; then
phelp
exit 1
fi
name=${0##/}
OWD=$PWD
for file; do
cd $OWD
case "$file" in
*.tar.Z) ArchiveName=${file%%.tar.Z} zcat=zcat;;
*.tar.z) ArchiveName=${file%%.tar.z} zcat=pcat;;
*.tar.gz) ArchiveName=${file%%.tar.gz} zcat=gzcat;;
*) ArchiveName=$file
for ext in "" .Z .z .gz; do
if [ -f "$file.tar$ext" ]; then
file="$file.tar$ext"
break
fi
done
if [ ! -f "$file" ]; then
echo "$file: cannot find archive." 1>&2
continue
fi
;;
esac
if [ ! -r "$file" ]; then
echo "$file: cannot read." >&2
continue
fi
DirName=${ArchiveName##*/}
[ -d "$DirName" ] || {
mkdir "$DirName" || {
echo "$DirName: could not make archive directory." 1>&2
continue
}
}
cd $DirName || {
echo "$name: cannot cd to $DirName" 1>&2
continue
}
case "$file" in
/*) ;;
*) file=$OWD/$file ;;
esac
echo "Extracting archive $file into directory $DirName..."
case "$file" in
*.tar.Z|*.tar.z|*.tar.gz) $zcat $file | tar xvf -;;
*.tar) tar xvf $file;;
esac
echo "Done extracting archive $file into directory $DirName."
done
+45
View File
@@ -0,0 +1,45 @@
:
# @(#) uudec.sh 1.0 93/11/22
# 92/08/04 john@armory.com (John H. DuBois III)
# 93/11/22 Added help.
isfalse()
{
test 0 -eq "$1"
}
phelp()
{
"$name: process uuencoded files.
Usage: uudec [-h] filename ...
Options:
-h: Print this help."
}
name=${0##*/}
typeset -i force=0
while getopts "hf" opt; do
case "$opt" in
h) phelp; exit 0;;
f) force=1;;
*) echo "$Usage" 1>&2; exit 2;;
esac
done
shift $((OPTIND - 1))
for file; do
echo "$file"
while read b mode filename && [ "$b" != begin ]; do :; done < "$file"
if [ "$b" = begin ]; then
if [ -f "$filename" ] && isfalse $force; then
echo "Output file \"$filename\" exists. Not written."
else
uudecode "$file"
fi
else
echo "No begin line."
fi
done
+69
View File
@@ -0,0 +1,69 @@
#! /bin/bash
#
# original from:
# @(#) uuenc.ksh 1.0 93/09/18
# 93/09/18 john h. dubois iii (john@armory.com)
#
# conversion to bash v2 syntax by Chet Ramey
istrue()
{
test 0 -ne "$1"
}
isfalse()
{
test 0 -eq "$1"
}
phelp()
{
echo "$name: uuencode files.
$Usage
For each filename given, $name uuencodes the file, using the final
component of the file's path as the stored filename in the uuencoded
archive and, with a .${SUF} appended, as the name to store the archive in.
Example:
$name /tmp/foo
The file /tmp/foo is uuencoded, with \"foo\" stored as the name to uudecode
the file into, and the output is stored in a file in the current directory
with the name \"foo.${SUF}\".
Options:
-f: Normally, if the file the output would be stored in already exists,
it is not overwritten and an error message is printed. If -f (force)
is given, it is silently overwritten.
-h: Print this help."
}
name=${0##*/}
Usage="Usage: $name [-hf] <filename> ..."
typeset -i force=0
SUF=uu
while getopts :hf opt; do
case $opt in
h) phelp; exit 0;;
f) force=1;;
+?) echo "$name: options should not be preceded by a '+'." 1>&2 ; exit 2;;
?) echo "$name: $OPTARG: bad option. Use -h for help." 1>&2 ; exit 2;;
esac
done
# remove args that were options
shift $((OPTIND - 1))
if [ $# -lt 1 ]; then
echo "$Usage\nUse -h for help." 1>&2
exit
fi
for file; do
tail=${file##*/}
out="$tail.${SUF}"
if isfalse $force && [ -a "$out" ]; then
echo "$name: $out: file exists. Use -f to overwrite." 1>&2
else
uuencode $file $tail > $out
fi
done
+137
View File
@@ -0,0 +1,137 @@
#! /bin/bash
#
# original from:
# vtree: visual directory tree
# @(#) vtree.sh 1.1 91/07/01
# 90/04 john h. dubois iii (john@armory.com)
# 91/07/01 fixed bug that caused problems when dir given on command line,
# added some info to help, changed to 4-space indenting
#
# conversion to bash v2 syntax done by Chet Ramey
#
help=\
"Syntax: vtree [startdir] [namelen=#] [linelen=#]
If startdir is not specified, tree will start at current dir.
namelen specifies the minimum number of characters of a directory name that
are guaranteed to be printed.
This is a tradeoff between the number of tree levels that can fit on a
screen line and the number of chars of each dir name that can be printed.
In most cases it will be possible to print more than namelen characters of
the name (a name up to namelen+1 chars will always be printed in full),
but in some cases truncation down to namelen chars will occur.
If truncation occurs, a '>' is printed at the end of the name.
namelen=8 (the default) typically causes about 5 dirs/1000 to be truncated.
namelen=7 typically causes about 10 dirs/1000 to be truncated.
namelen=8 will allow 6 full length dirs to be printed in 79 columns.
namelen=7 will allow 7 full length dirs to be printed in 79 columns;
linelen specifies the maximum number of characters to print on one screen
line. All characters beyond this are truncated. The default is 1024.
To avoid line wrap on an 80 column terminal with autowrap, use linelen=79.
"
for i in "$@"; do
case $i in
-h) echo "$help"; exit;;
*=*)
vars="$vars $i"
;;
*)
if [ ! -x $i ] || [ ! -d $i ]; then # arg must be a dir and executable
echo "$i: directory not accessible."
exit
fi
cd $i
;;
esac
shift
done
pwd # print path of root of tree
# find all directories depth first; ignore permission errors
find . -type d -print 2> /dev/null | \
gawk -F/ '
# Do this block for NR == 1 instead of BEGIN because command line var
# assignments are not done until after BEGIN block is executed.
NR == 1 {
if (namelen)
MaxLen = namelen;
else
MaxLen = 8;
if (!linelen)
linelen = 1024
HSpace = substr(" ",1,MaxLen); # used to indent tree
n = 0; # number of dirs found on one major branch
}
$0 != "." { # do for every line produced by find except tree root dir
if (NF == 2 && n > 0) # print major branch whenever a new one starts
list();
Depth[n] = NF - 1; # record depth and name of dir
Name[n++] = $NF;
}
END {
list() # print last major branch
}
function list() {
Line = Name[0]; # initialize first line of branch to be branch base
for (i = 1; i < n; i++) { # for each name in major branch
if (Depth[i] == Depth[i-1] + 1)
AddHLink(); # if moving deeper into branch, use same line
else {
print substr(Line,1,linelen); # last line is done; print it
Line = ""; # start new line
# print indentation, vert links, and vert/horiz links
for (d = 1; d < Depth[i] - 1; d++) # for each level of indentation
# if a vert. link has been established for this level
if (VLink[d])
Line = Line HSpace " | ";
else # print empty indentation
Line = Line HSpace " ";
# Print last part of vert. link
if (VLink[d] == i) {
VLink[d] = 0; # mark level for no vert link
Line = Line HSpace " \\--";
}
else
Line = Line HSpace " |--";
}
Line = Line Name[i]; # Add dir name to line
}
print substr(Line,1,linelen); # print last line of major branch
n = 0; # reset name counter
}
function AddHLink() {
NDepth = Depth[i]; # Depth of this name
VLink[NDepth - 1] = 0;
# search until a name found at a level less than this one
for (j = i + 1; j < n && Depth[j] >= NDepth; j++)
# keep track of last name that VLink should connect to
if (Depth[j] == NDepth)
VLink[NDepth - 1] = j;
if (VLink[NDepth - 1]) {
NLine = substr(Line,1,(NDepth - 2) * (MaxLen + 4) + MaxLen + 1);
if (length(NLine) < length(Line))
Line = substr(NLine,1,length(NLine) - 1) ">"
else
Line = NLine;
Line = Line substr("--------------+--",
18 - ((NDepth - 1) * (MaxLen + 4) - length(Line)));
}
else {
NLine = substr(Line,1,(NDepth - 2) * (MaxLen + 4) + MaxLen + 3);
if (length(NLine) < length(Line))
Line = substr(NLine,1,length(NLine) - 1) ">"
else
Line = NLine;
Line = Line substr("-----------------",
1,(NDepth - 1) * (MaxLen + 4) - length(Line));
}
}
' $vars
+111
View File
@@ -0,0 +1,111 @@
#! /bin/bash
#
# original from:
# @(#) where.ksh 1.1 94/07/11
# 91/01/12 john h. dubois iii (john@armory.com)
# 92/08/10 Only print executable *files*.
# 92/10/06 Print err msg if no match found.
# 92/11/27 Added implicit *
# 93/07/23 Print help only if -h is given.
# 94/01/01 Added -x option
# 94/07/11 Don't bother with eval
#
# conversion to bash v2 syntax done by Chet Ramey
name=${0##*/}
Usage="Usage: $name [-hx] 'pattern' ..."
typeset -i exact=0
phelp()
{
echo "$name: find executable files in PATH that match patterns.
$Usage
$name searches each directory specified in the PATH environment variable
for executable files that match the specified patterns. Patterns are
given as Korn shell filename patterns. They are surrounded by implicit
'*' characters, so that \"foo\" will match any executble file whose name
contains contains \"foo\". This can be overridden by using '^' and '$' to
force a match to start at the beginning and end at the end of a filename
respectively. Characters that are special to the shell must generally
be protected from the shell by surrounding them with quotes.
Examples:
$name foo
lists all executable files in PATH that contain foo.
$name '^b*sh$'
lists all executable files in PATH that start with b and end with sh.
An error message is printed if a no matching file is found for a pattern.
Options:
-h: Print this help.
-x: Find exact matches only; equivalent to putting ^ and $ at the start
and end of each pattern."
}
istrue()
{
test 0 -ne "$1"
}
isfalse()
{
test 0 -eq "$1"
}
while getopts "xh" opt; do
case "$opt" in
x) exact=1;;
h) phelp ; exit 0;;
*) echo -e "$Usage\nUse -h for help." 1>&2; exit 2;;
esac
done
shift $((OPTIND-1))
set +f # make sure filename globbing is on
Args=("$@") # save args
OIFS=$IFS
IFS=: # Make PATH be split on :
Paths=($PATH)
IFS=$OIFS
for arg in "${Args[@]}"; do
# get rid of leading ^
if istrue $exact; then
arg=${arg}
else
case "$arg" in
^*) arg=${arg#?};;
*) arg="*$arg" ;; # Pattern is not anchored at start
esac
fi
# get rid of trailing $
if istrue $exact; then
arg="$arg"
else
case "$arg" in
*\$) arg=${arg%?} ;;
*) arg="$arg*" ;;
esac
fi
found=0 # Pattern not found yet
Patterns=
# Make a pattern for each element of PATH
for PathElem in "${Paths[@]}"; do
[ -z "$PathElem" ] && PathElem=.
Patterns="$Patterns $PathElem/$arg"
done
# Find all pattern matches that are executable regular files.
for file in $Patterns; do
if [ -x "$file" ] && [ -f "$file" ]; then
echo "$file"
found=1
fi
done
if [ $found = 0 ]; then
echo "$arg: not found." 1>&2
fi
done