Warning!
|
The shell can read commands from its standard input or from a file.
To run a series of commands that can change, you may want to use one
program to create the command lines automatically - and pipe that program's
output to a shell, which will run those "automatic" commands. |
Here's an example.
[3]
You want to copy files from a subdirectory and all its subdirectories
into a single directory.
The filenames in the destination directory can't conflict; no two
files can have the same name.
An easy way to name the copies is to replace each slash (/
)
in the file's relative pathname with a minus sign (-
).
[4]
For instance, the file named lib/glob/aprog.c
would be copied to
a file named lib-glob-aprog.c
.
You can use
sed
(34.1
)
to convert the filenames and output cp
commands like these:
cp from
/lib/glob/aprog.c to
/lib-glob-aprog.c
cp from
/lib/glob/aprog.h to
/lib-glob-aprog.h
...
However, an even better solution can be developed using
nawk
(33.12
)
.
The following example uses
find
(17.1
)
to make a list of pathnames, one per
line, in and below the copyfrom
directory.
Next it runs nawk
to create the destination
file pathnames (like to
/lib-glob-aprog.c
) and write the
completed command lines to the standard output.
The shell reads the command lines from its standard input, through the
pipe.
This example is in a script file because it's a little long to type at a prompt.
But you can type commands like these at a prompt, too, if you want to:
#!/bin/sh
find copyfrom -type f -print |
nawk '{ out = $0
gsub("/", "-", out)
sub("^copyfrom-", "copyto/", out)
print "cp", $0, out }' |
sh
If you change the last line to sh -v
, the shell's
verbose option (46.1
)
will show each command line before executing it.
If the last line has sh -e
, the shell will quit immediately
after any command returns a non-zero
exit status (44.7
)
-
that
might happen, for instance, if the disk fills up and cp
can't
make the copy.