I have a directory with a bunch of subdirectories in it. Thus
/usr/local/src/ccl/ccl-1.8/x86-headers$ ls
elf gl gmp gnome2 gtk2 jni libc
Each of these directories has a further subdirectory C
inside it, which contains a file populate.sh
. I want to create a parallel group of subdirectories with the same structure, but with a random value appended to the directory name (the random value should be the same in all cases), and only containing the C subdirectory with the populate.sh
file. These directories contain other files besides the populate.sh
file.
This is for a makefile, so for simplicity should probably use standard unix utilties. I'm thinking find with the -exec
flag, or possibly xargs
would work, but I'm having trouble making sense of the documentation, and I have little experience with shell scripting. Perl might work, but I have not used it, and would prefer not to use it here.
I've been using something like mktemp -u --tmpdir=.
to generate a random string in the past, but it is hardly ideal, so I'm open to other suggestions. Ideally I'd like a name that looks like libc.tmp_xw3st
. Ie. tmp_
followed by a 5 digit alphanumeric string.
So far, I've got a way of getting a listing of the top level directories. 🙂
find . -maxdepth 1 -type d -print0
../gmp./jni./gl./elf./libc./gtk2./gnome2
A fuller directory listing is at the end of this posting. To summarize, I want to create additional directories like x86-headers/libc.tmpvalue
, which only contains the further file x86-headers/libc.tmpvalue/C/populate.sh
.
A sketch of a possible approach is to handle this in two steps as follows:
Step 1: Run over the list of top level directories using find
, and create a corresponding directory structure eg dirname.tmpvalue/C/
using exec
or piping to xargs
and using mkdir -p
.
Step 2: Run over the list of top level directories again and cp populate.sh
into the C
subdirectories. This is a bit sloppy, because the list of directories in theory could have altered between the two invocations of find
, but this is not an issue in this case.
/usr/local/src/ccl/ccl-1.8/x86-headers$ ls -laR
[...]
./jni:
total 96
drwxr-sr-x 3 faheem staff 4096 Jul 31 00:53 .
drwxr-sr-x 9 faheem staff 4096 Jul 31 00:53 ..
drwxr-sr-x 2 faheem staff 4096 Jul 31 00:53 C
-rw-r--r-- 1 faheem staff 19535 Jul 31 00:53 constants.cdb
[more .cdb files]
./jni/C:
total 12
drwxr-sr-x 2 faheem staff 4096 Jul 31 00:53 .
drwxr-sr-x 3 faheem staff 4096 Jul 31 00:53 ..
-rw-r--r-- 1 faheem staff 148 Jul 31 00:53 populate.sh
./libc:
total 1276
drwxr-sr-x 3 faheem staff 4096 Jul 31 00:53 .
drwxr-sr-x 9 faheem staff 4096 Jul 31 00:53 ..
drwxr-sr-x 2 faheem staff 4096 Jul 31 00:53 C
-rw-r--r-- 1 faheem staff 593125 Jul 31 00:53 constants.cdb
[more .cdb files]
./libc/C:
total 20
drwxr-sr-x 2 faheem staff 4096 Jul 31 00:53 .
drwxr-sr-x 3 faheem staff 4096 Jul 31 00:53 ..
-rwxr-xr-x 1 faheem staff 10544 Jul 31 00:53 populate.sh
Best Answer
This is not a job for
find
, since there is no recursion involved.Remove the
-p
option tocp
if you don't want to preserve the files' modification time.To generate a random suffix, BSD/Linux
mktemp
is as portable as it gets.If you want something vaguely random-looking and POSIX-compliant, this gives a string that changes every second and varies from location to location; you can't really do better with only POSIX tools:
If you put this code in a makefile, remember to:
$
signs;;
instead to separate shell instructions (you can use backslash+newline+tab to put a line break in the makefile, but that sequence is removed to build the shell command);set -e
, so that it aborts if there is any error.