• merge latest version of rannotate code from corecode
[alioth/cvs.git] / contrib / descend.sh
1 #! /bin/sh
2 #
3 # Copyright (C) 1995-2005 The Free Software Foundation, Inc.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2, or (at your option)
8 # any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # descend - walk down a directory tree and execute a command at each node
16
17 fullname=$0
18 name=descend
19 usage="Usage: $name [-afqrv] command [directory ...]\n
20 \040\040-a\040\040All: descend into directories starting with '.'\n
21 \040\040-f\040\040Force: ignore errors during descent\n
22 \040\040-q\040\040Quiet: don't print directory names\n
23 \040\040-r\040\040Restricted: don't descend into RCS, CVS.adm, SCCS directories\n
24 \040\040-v\040\040Verbose: print command before executing it"
25
26 # Scan for options
27 while getopts afqrv option; do
28     case $option in
29         a)
30             alldirs=$option
31             options=$options" "-$option
32             ;;
33         f)
34             force=$option
35             options=$options" "-$option
36             ;;
37         q)
38             verbose=
39             quiet=$option
40             options=$options" "-$option
41             ;;
42         r)
43             restricted=$option
44             options=$options" "-$option
45             ;;
46         v)
47             verbose=$option
48             quiet=
49             options=$options" "-$option
50             ;;
51         \?)
52             /usr/5bin/echo $usage 1>&2
53             exit 1
54             ;;
55     esac
56 done
57 shift `expr $OPTIND - 1`
58
59 # Get command to execute
60 if [ $# -lt 1 ] ; then
61     /usr/5bin/echo $usage 1>&2
62     exit 1
63 else
64     command=$1
65     shift
66 fi
67
68 # If no directory specified, use '.'
69 if [ $# -lt 1 ] ; then
70     default_dir=.
71 fi
72
73 # For each directory specified
74 for dir in $default_dir "$@" ; do
75
76     # Spawn sub-shell so we return to starting directory afterward
77     (cd $dir
78
79         # Execute specified command
80         if [ -z "$quiet" ] ; then
81             echo In directory `hostname`:`pwd`
82         fi
83         if [ -n "$verbose" ] ; then
84             echo $command
85         fi
86         eval "$command" || if [ -z "$force" ] ; then exit 1; fi
87
88         # Collect dot file names if necessary
89         if [ -n "$alldirs" ] ; then
90             dotfiles=.*
91         else
92             dotfiles=
93         fi
94
95         # For each file in current directory
96         for file in $dotfiles * ; do
97
98             # Skip '.' and '..'
99             if [ "$file" = "." -o "$file" = ".." ] ; then
100                 continue
101             fi
102
103             # If a directory but not a symbolic link
104             if [ -d "$file" -a ! -h "$file" ] ; then
105
106                 # If not skipping this type of directory
107                 if [ \( "$file" != "RCS" -a \
108                         "$file" != "SCCS" -a \
109                         "$file" != "CVS" -a \
110                         "$file" != "CVS.adm" \) \
111                         -o -z "$restricted" ] ; then
112
113                     # Recursively descend into it
114                     $fullname $options "$command" "$file" \
115                     || if [ -z "$force" ] ; then exit 1; fi
116                 fi
117
118             # Else if a directory AND a symbolic link
119             elif [ -d "$file" -a -h "$file" ] ; then
120
121                 if [ -z "$quiet" ] ; then
122                     echo In directory `hostname`:`pwd`/$file: symbolic link: skipping
123                 fi
124             fi
125         done
126     ) || if [ -z "$force" ] ; then exit 1; fi
127 done