# [Copyright 1998 Peter Maydell ] # Not a shell script; the comments make the syntax invalid. # Comments are on lines starting with '#'; if you strip them all out # then the syntax is OK. # Standard boilerplate to create a working directory /tmp/t # Note that the last \ on each line is the shell line continuation marker. cd /tmp && mkdir t && cd t && \ # More standard boilerplate. -noleaf is important so that find doesn't # do an optimisation which causes it to not see directories created # during the execution of commands relating to the parent directory. find . -noleaf # This is the standard way to do something as an initialisation routine # (similar concept to awk's BEGIN section): since /tmp/t is empty, the # first filename to be processed is '.' # We create 2 (ie /tmp/t/2) as a subdirectory to start the ball rolling, # and print '2', since 2 is a prime. -path . -exec mkdir 2 \; -printf '2\n' \ # This is the termination condition: if we're processing the directory # '100n' then we should stop here. We terminate by simply not creating # a subdirectory. -o -name 100n \ # The rest of this handles the general case. Suppose we are in a directory # named x-1. Then we create a subdirectory x if x is prime or xn if x # is not prime. The result is to create a directory structure # /tmp/t/2/3/4n/5/6n/7/8n/9n/10n/11/... # First we need to find out whether x is prime or not. To do this we # exec a process which exits successfully if x is not prime: -o -exec sh -c "find . -path . -o -name '*n' \ -o -exec expr \( \( \( {} : '.*/\([^n]*\)' \) + 1 \) / \{\} : '.*/\(.*\)' \ \) \* \{\} : '.*/\(.*\)' - \( {} : '.*/\([^n]*\)' \) - 1 ';' | grep '^0$' \ >/dev/null " \; \ # Phew. What this does is run a sub-find which executes expr for # each directory which doesn't end 'n' (ie all the primes). # The expr uses {} : '.*/\([^n]*\)' to extract the final number # (eg given ./2/3/4n/5 it evaluates to 5) and thus the find essentially # evaluates ((x+1)/n) * n - x - 1 for all prime n between 2 and x. # This is zero for some n iff x+1 is not prime, so we grep for that, # throwing away the output of the grep and just using its exit status # (true for if it matched a '0'). Note that we use {} to get the top # level find to substitute its filename, and \{\} to get the sub-find # to do the substitution. This works because the top find sees \{\} # but the argument presented to the subfind has gone through an extra # level of shell quoting so it gets {} (and gets a substituted file # name where the top find saw {}). # # We now use the fact that -foo -bar is equivalent to -foo -a -bar, # so if -foo fails we wouldn't do -bar. # If the subfind succeeds we execute this mkdir; otherwise we # continue executing after the next -o. # If we're currently in ./2/3/4n/5, this creates the directory # ./2/3/4n/5/6n, using expr to do the addition and the shell for # quoting services (backticks). -exec sh -c "mkdir {}/\`expr {} : '.*/\([^n]*\)' + 1\`n" \; \ # if the sub-find failed, we do a similar thing, but without the trailing 'n' -o -exec sh -c "mkdir {}/\`expr {} : '.*/\([^n]*\)' + 1\`" \; \ # and we also print x+1, since it's prime. We do this by printing a # listing of the current directory (which for eg ./2/3/4n will have # a single entry '5'); this is both for variety and to avoid using a # grotty expr pattern again. -exec sh -c "echo \`ls {}\`" \; \ # This is the standard trailer to remove all the directories we created. # We can't do that as part of the find command because it confuses it... && cd /tmp && rm -r t # # See? Perfectly comprehensible.