for loop problems

I have a script that loops through a list of users to list files owned by these users

for u is `cat users.list`
do
echo $u >> result.out
find /home -user $u >> result.out
find /var -user $u >> result.out
find /opt -user $u >> result.out
find /usr -user $u >> result.out
done

an so on...
when running this loop, I get this error "find: 0652-012 The user name does not exist." for each time the loop iterates. mind you that echo prints out the correct user name each time. its just the find command thats having problems.

And when I run find commands without looping, one user at a time i get results just fine. Is there something I'm missing?

What particular user name string does find complain about?

All of them. echo prints all the users in the list, and find give errors on all users.

file sample:

adm
bin
daemon
db2inst
db2inst1
dpower
esaadmin
ipsec
itmuser
mqbrk
mqm
nobody
snapp
sys
tdiuser
tivoli
wasadmin
wpsadmin

I'm not sure what causes the error, because here could be several reasons, unprintable characters in your user-list file being probably the most common.

Still, there are some problems with your code anyway so it might be a good idea to correct these and test then:

1) old and deprecated syntax

backticks are only supported for backwards compatibility any more, so PLEASE don't use them: they are hard to read when mixed with quotation marks (single, double), they cannot be nested and they do have no advantage whatsoever for the modern way of doing the same: the "$(....)" construct. Actually this can do all the things backticks can not.

2) Your use of a "for"-loop

Bear in mind that a subshell invocation basically is expanded to text before the main command is parsed. That means: when the shell is evaluating a line first whatever is the result (output) of the command in the subshell is evaluated, then this replaces the subshell invocation, then the remaining command is evaluated.

It follows that all is fine as long as you don't hit the maximum length for input lines to the shell (usually 4096 or 8192 characters). If your list is really long the script will break with a "line too long" error.

As a general rule: if you work on lists of undetermined length do not use the "for"-loop but the "while"-loop with a pipeline. Instead of

for WORD in $(some process) ; do
   something $WORD
done

write

some process | while read WORD ; do
    something $WORD
done

3) Don't take variables for granted.

Yes, the shell allows this usage of variables that have not been declared before. No, you should still not rely on this mechanism. First, because it is a good idea to introduce variables explicitly with a "typeset"-statement, which gives you the opportunity to document what you write:

#! /bin/ksh
# this is a sample script

typeset USER=""             # buffer for cycling through users

cat /path/to/userlist | while read USER ; do
     do_something $USER
done

exit 0

This will explain beyond any doubt what "$USER" is used for. This is maintenance-friendly once you have longer and more complex scripts.

Second, because it allows to declare some properties of the variable explicitly (i.e. type integer with the "-i" option of typeset or "-x", which makes this variable known throughout subshells). It is even possible to format your variable with some of the options to "typeset" ("-L"= convert to lowercase, "-U" to uppercase, etc.)

So, after all this, here is how i would have written your script:

#! /bin/ksh

# some explanation of what it does here. Even more so if it is to be put in
# cron. To avoid the "number-one-cron-scripts-problem" *) you should habitually
# set your environment in every script.

. /etc/environment                   # set some standard environment

typeset chUser=""                    # buffer for cycling through user names
typeset fIn="/path/to/users.list" # file with user names, one at a line
typeset fOut="/path/to/result.out" # log file with output

cat "$fIn" |\
while read chUser ; do
     echo "$chUser" >> $fOut
     find /home -user "$chUser" >> $fOut
     find /var -user "$chUser"  >> $fOut
     find /opt -user "$chUser"  >> $fOut
     find /usr -user "$chUser"  >> $fOut
done

exit 0

I hope this helps.

bakunin

__________________

*) For an explanation of Cron Problem Number One