Listing 1: The Indir script
#! /usr/gnu/bin/bash
#
# Copyright (C) 1994 Martin Leisner
# leisner@sdsp.mc.xerox.com
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# Inspired by the X11R5 script
# $Id: lndir.sh,v 1.12 1995/02/13 13:51:14 leisner Exp leisner $
# Major enhancements include:
# A filter directory list
# Ability to filter files (which match regular expressions
# (i.e. *.o)
# An update option
function cp
{
command /usr/gnu/bin/cp $*
}
function mkdir
{
command /usr/gnu/bin/mkdir $*
}
default_filter_directories="CVS RCS SCCS"
filter_list=${LNDIR_FILTERLIST:-$default_filter_directories}
function pushd {
builtin pushd $1 2>/dev/null 1>& 2
if [ $? -ne 0 ]; then
echo pushd $1 failed at $PWD
fi
}
function popd {
builtin popd 2>/dev/null 1>& 2
}
function echo {
builtin echo -e "$*"
}
function match
{
if [ $# -ne 2 ]; then
echo need to call match with 2 argument, called with $# arguments
exit
fi
case $1 in
$2)
return 0
;;
*)
return 1
;;
esac
}
# see if arg1 in in $filter_filter
# return 1 for not matched
function check_file
{
if [ $# -ne 1 ]; then
echo check_file needs one arg
exit
fi
if [ -z "$file_filter" ]; then
return 1
fi
set -f
for i in "$file_filter"
do
match $1 $i
if [ $? -eq 0 ]; then
set +f
return 0
fi
done
set +f
# not matched
return 1
}
function usage {
echo "Usage: $0 [-v] [-u] [-s] [-f files] [-i dirs] source [destination ]"
echo "\t-v will be verbose when running"
echo "\t-s will give statistics at the end"
echo "\t-u will only do updates (new files, without pruning)"
echo "\t-f will filter files (will be regexp)"
echo "\n\t-i will specify a list of directories to filter"
echo "\tDefault is $default_filter_directories"
if [ -z "$LNDIR_FILTERLIST" ]; then
echo "\tOr use environment variable LNDIR_FILTERLIST"
else
echo "\tLNDIR_FILTERLIST = $LNDIR_FILTERLIST"
fi
exit 1
}
# figure out if argument is in the filter directory list
# return 1 if we don't care, 0 if we have a match
function filter_directories {
if [ X"$filter_list" = "X" ]; then
return 1 # no filter list
fi
for i in $filter_list
do
if [ $i = $1 ]; then
return 0
fi
done
return 1
}
# if not a directory, print a message and exit
function test_dirs
{
for i in $*
do
if [ ! -d $i ]; then
echo $i is not a directory relative to $PWD
exit 1
fi
done
}
function copy_tree {
# $1 is source, $2 is destination, $3 is a string of blanks we increment
# when we submit
local directories_to_copy=0
local files_to_copy=0
local submit_string="$3 "
# if [ ! -z $verbose ]; then
# echo copy_tree from $1 to $2 at $PWD
# fi
if [ $# -ne 3 ]; then
echo have incorrect count $*
exit 1
fi
pushd $2
test_dirs $1
pushd $1
local files="$(echo *)"
popd
if [ "$files" = '*' ]; then
echo $1 is empty, PWD=$PWD
popd
return # nothing to do
fi
local to_move=""
local directories=""
local to_link=""
# check to see if starting with absolute path
case $1 in
/* ) local prefix=$1 ;;
* ) local prefix=../$1 ;;
esac
for file in $files
do
local try=$1/$file
if [ ! -e $try ]; then
# this also gets rid of hanging symlinks
echo "something wrong, $try doesn't exist at $PWD"
continue
fi
if [ -L $try ]; then
set -v
# figure out if symbolic link is a directory
if [ ! -d $try ]; then
check_file $file
else # must be a
filter_directories $file
fi
# code is whether or not to file
if [ $? -ne 1 ]; then
to_link="$to_link $file"
fi
set +v
continue
fi
# must not be a symlink
if [ -f $try ]
then
if [ ! -z "$file_filter" ]; then
check_file $file
if [ $? -eq 0 ]; then
continue
fi
fi
to_move="$to_move $try"
files_to_copy=$[files_to_copy+1]
# link all files
else
filter_directories $file
if [ $? -eq 1 ]
then
directories_to_copy=$[directories_to_copy+1]
directories="$directories $file"
fi
fi
done
# make directies and recurse into them
if [ ! -z "$directories" ]; then
mkdir $directories
num_mkdirs=$[num_mkdirs+1]
if [ $verbose ]; then
echo making $directories
fi
if [ $? -ne 0 -a ! -z "$update" ]; then
echo have problem making $directories
echo aborting
exit 1
fi
for i in $directories
do
echo "$submit_string" $i/
copy_tree $prefix/$i $i "$submit_string"
done
fi
# link the files...
if [ ! -z "$to_move" ]; then
cp -s $to_move .
if [ $? -ne 0 -a ! -z "$update" ]; then
echo had an error in copy $to_move
fi
num_copies=$[num_copies+1]
if [ $verbose ]; then
echo linking $files_to_copy files
fi
fi
# link the sym links
if [ ! -z "$to_link" ]; then
cp -a $to_link .
if [ $? -ne 0 -a ! -z "$update" ]; then
echo had an error in cp -a $to_link .
fi
num_copies=$[num_links+1]
if [ $verbose ]; then
echo linking $to_link symfiles
fi
fi
popd
}
echo $DIRFROM $DIRTO
# filter_list="$filter_list " $2
# echo filtering $filter_list
if [ $# -eq 0 ]; then
usage
fi
# set to true when we want statistics
statistics=""
# set to echo all operations
verbose=""
# set when we're in update mode
update=""
# filter files which match this regexp
file_filter=""
while getopts svf:t:i: c; do
case $c in
s) statistics=true ;;
v) verbose=true ;;
u) update=true ;;
i)
filter_list="$OPTARG"
;;
f)
file_filter="$OPTARG"
;;
*)
echo illegal argument
usage
;;
esac
done
shift $(expr $OPTIND - 1 )
DIRFROM=$1
if [ $# -eq 2 ];
then
DIRTO=$2
else
DIRTO=.
fi
if [ ! -d $DIRTO ]
then
echo "$0: $DIRTO is not a directory"
usage
fi
if [ ! -d $DIRFROM ]
then
echo "$0: $DIRFROM is not a directory"
usage
fi
# this isn't really sufficient -- we need to do inode/device numbers
if [ `(cd $DIRFROM; pwd)` = $PWD ]
then
echo "$pwd: FROM and TO are identical!"
exit 1
fi
# initialize counts
num_copies=0
num_links=0
num_mkdirs=0
total_directories=0
total_files=0
copy_tree $DIRFROM $DIRTO ""
if [ ! -z $statistics ]; then
echo Num copies = $num_copies
echo Num mkdirs = $num_mkdirs
echo Num links = $num_links
fi
|