On Sun, 24 Jun 2001, James R. Van Zandt wrote:
> I would appreciate some pointers on this.
The key thing to realize in this whole game is that programs do not see what
you type at the shell prompt. The shell parses your command. It expands any
variables, wildcards, etc., and does other shell magic. It then takes the
resulting list and passes it, via the argv[] array, to the program you
specified. Most programs expect each argument to name one and only one file.
Each argument is a null-terminated string, so spaces or other special
characters usually do not matter. Exceptions are the rule, of course, but
this is the essential concept.
With that in mind, your goal becomes getting the shell (or a some other
utility) to pass the appropriate list of arguments to the program(s) you want.
> For example, I often use this idiom:
>
> for x in *.txt; do sed 's/which/that/' $x >foo && mv foo $x; done
>
> Which would of course break if any filename had spaces.
Enclose your variables in double-quotes. For example (broken up into
multiple lines for readability):
for x in *.txt; do
sed 's/which/that/' "$x" > foo && mv foo "$x"
done
The double-quotes (DQs) tell the shell to expand any variables inside the
quotes, but to ignore any special characters in the result of that expansion.
This keeps stars, spaces, and other magic characters from screwing up your
commands.
One thing that may be confusing is that the shell only scans the result of
variable expansion for new special characters. It does not scan the result of
wildcard expansion. Thus, the construct
*.txt
results in a list of file names, which can safely contain spaces or other
weird characters. It is only when you stuff something into a variable that
things get tricky. (Well, not "only".)
> I know about the -exec and -print0 options of find, but AFAIK -exec only
> works with a single command and -print0 only works with a few programs
> that can accept null-delimited filenames.
The program xargs(1) has a "-0" (digit-zero, not letter-oh) option which
comes in very handy when used in conjunction with the "-print0" option of
find(1). It tells xargs to expect a list of null-terminated list on stdin.
xargs will pass those arguments to the given command directly, with no shell
being involved.
> Do you have something else in mind?
Someone mentioned dollar-at ($@) and dollar-star ($*) but did not go into
detail. Unquoted, dollar-star and dollar-at function the same. Placed in
DQs, their behavior changes. Dollar-star works like a regular variable placed
in DQs, in that all arguments are concatenated together into one big argument,
with spaces [1] separating the original argument. Dollar-at is magic.
Dollar-at in DQs acts as if you had specified each argument, one at a time, in
DQs. Thus, if you have three arguments, this
"$*"
will result in one big argument, but this
"$@"
will result in three arguments.
On a side note: Trying to write an email message about shell syntax is damn
hard! For the first time in my life, I see a use for HTML email. :-)
Footnotes
---------
[1] Technically speaking, the first character of $IFS is used; by default,
a space.
--
Ben Scott <[EMAIL PROTECTED]>
| The opinions expressed in this message are those of the author and do not |
| necessarily represent the views or policy of any other person, entity or |
| organization. All information is provided without warranty of any kind. |
**********************************************************
To unsubscribe from this list, send mail to
[EMAIL PROTECTED] with the following text in the
*body* (*not* the subject line) of the letter:
unsubscribe gnhlug
**********************************************************