RH(1L) RH(1L)
NAME
rh - recursive file locater (rawhide)
SYNOPSIS
rh [ -hlnrv ] [ -f filename ] [ -e rhprogram ]
[ -x command ] [const=value ...]
[path ...]
DESCRIPTION
Rh recursively searches the file system starting at each
given path. If no paths are listed, the recursive search
will start in the current working directory. For every
file that rh encounters it executes a rh program.
Programs for rh can come from the command line (with the
-e option), a file (with the -f option), or from the stan-
dard input (the default).
In its simplest form a rh program consists of a C expres-
sion containing variables, constants and the usual C oper-
ators. More advanced programs will contain statements and
function declarations.
Variables come in two flavors: built in variables and user
declared variables. Built in variables refer to some
attribute of a file (eg. size, mode, uid). As rh encoun-
ters files, the built in variables are updated. The vari-
able names are derived from the stat structure (see
stat(2)) with the leading "st " omitted. All other vari-
ables are user declared variables.
Constants are symbols that have been bound to values that
will not change. Many of the constants defined in the file
/usr/include/sys/stat.h are also constants in rh (eg. The
constant S IFMT is called IFMT in rh).
A Rh program consists of a series of expression/action
pairs of the form:
expr { action }
expr;
{ action }
BEGIN { action }
END { action }
In the first form, if expr evaluates to true (non-zero),
the associated action will be performed. When action is
omitted (the second form), the default action is to call a
function called ACTION(). In other words:
size > 1024;
is the same as,
2 Febuary 1990 1
RH(1L) RH(1L)
size > 1024 { ACTION(); }
The above programs run ACTION() on all files whose size is
greater than 1K. ACTION() in turn would print the file-
name.
size > 1024 && uid == UID
{ printf("Filename %s, size: %d\n",file,size); }
This would print out the filename and size for all files
larger than 1K, and owned by the person running the rh
process.
When expr is ommited (the third form) action will be per-
formed for every file.
By default ACTION() simply prints out the filename but
this behavior can be altered by the -l, -v and -x command
line options.
If the keyword BEGIN is used instead of an expression,
action is performed prior to the file search. If END is
used instead of expression, action will be executed at the
end.
OPTIONS
-h Causes rh to display a help message using the PAGER
environment variable. If PAGER is not defined,
SUBSTITUTE PAGER HERE will be used. The help
screen summarizes the command line options and
shows a list of available builtin functions, con-
stants, user defined functions, and variables.
-l Alters the default action so that the the filename
is printed in a manner similar to ls(1).
-n Prevents rh from reading the $HOME/.rhrc. Also
causes rh to ignore the contents of the RHPATH
environment variable. Shell scripts which invoke
rh should use the -n option to prevent a users
.rhrc from changing the behavior of rh.
-r Disables the recursive nature of rh. Rh will only
look at the files contained in path.
-v Verbose mode. Causes the -l option to output more
information and the -x option to print out the com-
mand executed and the return value.
-f filename
Uses filename as the name of a file containing a rh
program.
2 Febuary 1990 2
RH(1L) RH(1L)
If filename cannot be opened, the environment vari-
able RHPATH will be used as a search path. The ele-
ments of RHPATH should be separated by colons. If
RHPATH is not defined the default search path of
`` SUBSTITUTE RHPATH HERE '' is used.
-e rhprogram
This is similar to the -f option, except that the
input comes from the command line rather than a
file.
When both the -e and -f options are present, the file
specified by the -f option will be read first, followed by
the -e argument. Stdin will be read for more input when
only function declarations have been encountered.
-x command
Execute command using system(3) for each matching
file. The string command may contain a %f which
will be substituted with the full path name. A %F
(uppercase 'F') will be substituted with the base
name. For example, for the file "/etc/passwd" the
values for %f and %F would be: "/etc/passwd" and
"passwd", respectively.
const=value
Creates a constant called const and sets its value
to value. If value consists of all digit's const
will have an integer type, otherwise the constant
will created as a string. If value is omitted,
const will be set to the value 1.
THE RH LANGAUGE
Expressions
Rh expressions can contain constants, variables, function
calls and the following C operators:
! ~ - ++ -- * / %
+ - < <= > >=
== != & ^ |
<< >> && || ?:
+= -= *= %= >>=
<<= /= &= |= ^=
These operators share the same precedence and associativ-
ity as the C language. The relational operators ( < <= >
>= != == ) have been overloaded to deal with strings.
In contexts where an expression is being tested for its
boolean truth value, any non-zero integer is true and any
non-null string is true.
Variables can be of type string, integer, or array.
2 Febuary 1990 3
RH(1L) RH(1L)
Variables are declared by using them. The initial value
for a variable is 0 or the null string "". The type of a
variable can be changed by assigning to it a value of the
desired type.
Access to the characters within a string is done using the
substr() function. The first character of a string is at
index 0.
Strings and integer types are not compatable.
Arrays are collections of string and integer variables.
Access to array elements is done with the square brackets
``[ expr ]''. expr can be either an integer or a string.
The first element of an array is at index 0.
When an array is assigned, a copy is made of the original
array. When an array is passed to or returned from a func-
tion, a pointer to the array is used.
Action Statements
A rh action consists of a series of statements enclosed in
curly braces { }. A Statement is one of the following:
expression ;
while( expression ) statement
do statement while( expression );
if( expression ) statment [ else statement ]
for( expression ; expression ; expression ) statement
return expression;
break;
continue;
next; /* get the next filename and attributes */
{ [ statement ] ... }
;
Variables
Every time rh examines a new file it updates the following
built in variables:
VARIABLE DESCRIPTION
attr[] the attribute array (see below)
atime last accessed time
blksize prefered block size for I/O
blocks number of blocks used for the file
ctime last status change time
depth relative depth (origin 0)
dev device file resides on
file name of the current file
gid group ID of owner
ino inode number
mode mode flags
2 Febuary 1990 4
RH(1L) RH(1L)
mtime last modified time
nlink number of hard links
rdev device identifier
size size of file in bytes
uid user ID of owner
The attr variable is an array containing all the built in
variables. The following equivalencies show the relation-
ship between the elements of the attr[] array and the
corresponding variable.
atime == attr[ "atime" ]
blksize == attr[ "blksize" ]
blocks == attr[ "blocks" ]
...
uid == attr[ "uid" ]
When one of the built in variables is altered the corre-
sponding element in the attr[] array is also altered. Rh
does not permit new elements to be added to the attr[]
array.
Functions
The following is a description of the rh built in func-
tions. In the following description, n is a number, and s
is a string.
n = array(obj)
n = string(obj)
n = number(obj)
n = constant(obj)
Returns 1 if obj evaluates to an array, string,
number or constant object, otherwise 0 is returned.
n = atoi(s)
Convert the string ``s'' to a number.
s = dn(path)
s = bn(path)
Returns the directory portion of ``path'' (see
dirname(1)). For example, dn("/usr/lib/junk")
returns the string "/usr/lib". Bn() returns the
basename of ``path''.
n = chmod(path,mode)
Invokes chmod(2) to change the mode of ``path'' to
``mode''. 0 is returned on success, else the errno
is returned.
2 Febuary 1990 5
RH(1L) RH(1L)
n = chown(path,uid,gid)
Invokes chown(2), to change the owner and group of
``path''. 0 is returned on success, else the errno
is returned.
s = time(n)
Converts 'n' from a unix time() value into a
string. (see ctime(3)).
n = exec(fmt, a1, a2, a3, ...)
Uses system(3) after converting the arguments and
format string into a single string.
exit(n)
Terminates the current rh session and returns ``n''
to the shell.
s = fstype(path)
Returns a string describing the file system type
that path resides on. A return value of "nfs" would
indicate an NFS mounted file system. On some sys-
tems "4.2" would be returned to indicated disk
mounted file.
s = gets()
Reads a line of input from stdin, and returns that
line without the trailing newline.
uid = user("user name")
gid = group("group name")
"user name" = user(uid)
"group name" = group(gid)
Converts uid's and gid's to names, and converts
login names and group names to integers. When
passed a string, an integer is returned and vice
versa. If uid or gid is invalid, the empty string
is returned. If "user name" or "group name" is
invalid -1 is returned.
s = sprintf(fmt, a1, a2, a3, ...)
printf(fmt, a1, a2, a3, ...)
Same as printf(3) and sprintf(3), see below for a
description of the conversion characters that are
supported.
n = match(s,pattern)
2 Febuary 1990 6
RH(1L) RH(1L)
n = glob(s)
Returns 1 if the string ``s'' is matched by the
pattern. Otherwise 0 is returned. Glob is the same
as match(file,pattern).
n = ord(s)
The string ``s'' must be a string of length 1, the
single character is converted to a number and
returned. Useful for making comparisons on the
ascii code of a character in a filename.
s = perror(errno)
Returns the text error message from the numeric
``errno'' code.
print()
Prints out the contents of the ``file'' variable
followed by a newline.
n = prune()
Returns 0, and prunes the current search path such
that if the current file is a directory it will not
be searched.
a = stat(path)
Returns an array ``a'' which contains the result of
stat'ing the file path. The array is compatible
with the attr[] array. If the stat fails, the
type returned will a number whose value is equal to
the error code.
n = strlen(s)
Returns the length of the string ``s''.
s = substr(s,n,m)
Returns m characters starting at position n of
string ``s''. The first character of ``s'' is index
0. If the index is too large an empty string is
returned.
s = readlink(path)
Path is assumed to be a symbolic link. The contents
of the symbolic link is returned. A number is
returned if an error occurs.
2 Febuary 1990 7
RH(1L) RH(1L)
n = symlink(path1,path2)
Calls symlink(2) to create a symbolic link from
path2 to path1. An error number is returned on an
error. Otherwise 0 is returned.
n = unlink(path)
Removes the file path. An error number is returned
on an error, otherwise 0 is returned.
n = utimes(path,atime,mtime)
Sets the access time and last modified time of
path.
n = todate(year,month,day)
Converts the date indicated by year / month / day
into a unix integer.
n = ISREG(mode)
n = ISDIR(mode)
n = ISLNK(mode)
n = ISCHR(mode)
n = ISBLK(mode)
These functions are defined in SUBSTI-
TUTE RHCONF HERE .
NOTE: Functions without side effect will be pre-evaluated
if all the argument are constants. For example,
user("bin") would be pre-evaluated to the integer
6.
User functions are created with:
identifier (param1, param2, ...)
{ statements }
Where identifier is the name of the function to be defined
and param1, param2, ... are the parameters that the func-
tion will be called with.
In some cases you will want to undefine a functions so
that it can be redefined. A line of the form:
undefine id;
will undefine id. id must be the name of a user defined
function or a variable. This can be used to hide any
global variables used in a function. It can also be used
to redefine the ACTION() function.
2 Febuary 1990 8
RH(1L) RH(1L)
Built In Constants
CONSTANT DESCRIPTION
IFBLK see stat(2)
IFCHR see stat(2)
IFDIR see stat(2)
IFIFO see stat(2)
IFLNK see stat(2)
IFMT see stat(2)
IFREG see stat(2)
IFSOCK see stat(2)
ISGID see stat(2)
ISUID see stat(2)
ISVTX see stat(2)
UID user ID of user running rh
GID group ID of user running rh
PID process ID of this rh process
LFLAG equal to 1 if -l flag present
NOW equal to the current time
VERSION string equal to the rh version
VFLAG equal to 1 if the -v flag present
XARG string equal the -x option
Additional constants can be created on the command line,
see OPTIONS above.
Lexical conventions
Numbers may be entered in octal by preceding them with a
leading zero. Otherwise numbers are taken to be in deci-
mal.
Text enclosed in /* and */ is ignored.
The following character sequences have special meaning
when they occur inside a string.
\n replaced with a newline
\r replaced with a ^M (CR)
\" replaced with a double quote (").
\b replaced with a bell character.
\f replaced with a form-feed.
\v replaced with a vertical tab.
\t replaced with a tab.
\\ replaced with a back slash (\).
2 Febuary 1990 9
RH(1L) RH(1L)
Globbing characters
The glob() and match() functions accept a string contain-
ing a globbing pattern. The recognized metacharacters are:
``*'' to match any number of characters, including
zero (except that, as in the shell, it does
not match a leading ``.'');
``?'' to match any single character (except for a
leading ``.'');
``[SET]''
to match any character in the given set
(ranges can be included);
``[^SET]''
to match any character not in the given set;
``\\'' to escape the special meaning of any of the
above metacharacters.
Printf conversion characters
The following conversion characters are supported by
printf(), sprintf(), and exec() built in's.
%% Produces a % on output.
%d, %i Converts the signed integer argument into
its string representation.
%s Transfers the string argument to the out-
put.
%c Converts the integer argument to its char-
acter representation.
%f This is equivilant to using %s with the
file variable as the corresponding argu-
ment. %f requires no argument however.
%F Same as %f, but uses the basename of the
file variable.
%M Transforms its integer argument into an
ls(1) like mode string (ie. "r-x", "rw-",
"--S", ...). Suitable for the "user" and
"group" modes. The correct bits in the
mode field must be extracted in order to
use %M.
%m Same at %M, except it is designed for the
"other" modes (ie. "--T" ).
2 Febuary 1990 10
RH(1L) RH(1L)
%t Converts its integer argument into a single
character file type ('-' for a regular
file, 'd' for directory, and so on ...).
%T Converts a time value to a string using
ctime(3). The trailing newline is omitted.
%o Converts an unsigned integer into its Octal
representation.
%X, %x Converts an unsigned integer into its
Hexedecimal representation.
%b Converts an unsigned integer into its
Binary representation.
All conversion characters support a minimum and precision
value. See printf(3) for a description.
RESOURCE FILE
Rh initally looks for and reads a $HOME/.rhrc file. This
file can contain any valid rh input but typically only
contains function definitions.
SUBSTITUTE RHCONF HERE :
The ACTION() function is written in rh. It's definition is
contained in the file SUBSTITUTE RHCONF HERE . For added
customization it is possible to undefine the ACTION()
function and define your own.
EXAMPLES
This section gives examples for using rh to do the follow-
ing tasks:
1) Find files whose filenames have control
characters in them.
2) Add up the amount of disk space used in a
directory.
3) Display & remove files in /usr/spool/mail
that are not owned by a real user.
4) Change the group ownership of files from
one group to another.
EXAMPLE 1:
This example locates and displays files whose filenames
contain control characters in them.
This function returns "true" if any character in ``s''
2 Febuary 1990 11
RH(1L) RH(1L)
happens to be a control character:
cntl(s) {
for(i=0; c=substr(s,i,1); i++)
if( ord(c) < ord(" ") ) return 1;
return 0;
}
The following function cleans control characters using the
^A, ^B, ^C, ... notation:
clean(s)
{
k = "";
for(i=0; c=substr(s,i,1); i++)
if( (c=ord(c)) < ord(" ") )
k = sprintf("%s^%c",k,c+ord("@"));
else
k = sprintf("%s%c",k,c);
return k;
}
With cntl() and clean() defined above, we can do the fol-
lowing:
cntl(file) { file = clean(file); ACTION(); }
EXAMPLE 2:
This is a short rh program which counts the size of all
the files in a directory:
{ total += size; }
END { printf("%d\n",total); }
EXAMPLE 3:
Remove mail files that do not correspond to a real user:
user(uid) != bn(file) && !ISDIR(mode) {
ACTION();
list[ x++ ] = file;
}
END {
printf("\n-----------\n");
for(i=0; i<x; i++) {
printf("Remove %s? ",list[i]);
ans = gets();
if( substr(ans,0,1) == "y" || substr(ans,0,1) == "Y" )
unlink( list[i] );
}
}
The filenames are stored in an array and interactively
2 Febuary 1990 12
RH(1L) RH(1L)
removed after all files have been looked at.
EXAMPLE 4:
Assume that the following rh code is contained in the file
mvgrp:
BEGIN {
if( !constant(OLD) || !constant(NEW) ) {
printf("Usage: rh -f mvgrp OLD=oldgrp NEW=newgrp\n");
exit(1);
}
old = number(OLD) ? OLD : group(OLD);
new = number(NEW) ? NEW : group(NEW);
}
{
if( fstype(file) == "nfs" )
prune();
else if( gid == old ) {
ACTION();
chown(file,uid,new);
}
}
This script prunes nfs mounted directories. OLD and NEW
are expected to be constants defined on the command line;
the BEGIN section checks that is so. To change all files
owned by group ID "staff" to group ID "bin", you would
type:
rh -lv -f mvgrp OLD=staff NEW=bin
Note that groups numbers can be used instead of the group
name.
FILES
$HOME/.rhrc - Resource file for rh
SUBSTITUTE RHCONF HERE - Definition of the ACTION() function
SUBSTITUTE BINDIR HERE /rh - The rh executable
SUBSTITUTE RHPATH HERE - Default search path for rh scripts
SEE ALSO
find(1), ls(1), stat(2), chmod(2)
The C programming language.
VERSION
RH - Version 4.0
AUTHOR
Ken Stauffer (University of Calgary)
Email: ken@cpsc.ucalgary.ca
