Re: commands to manipulate files
2008-04-28, 23:08(-07), Nezhate:
[...]
> mop2: Thanks for your . but can you explain me what the next line
> do (I'm newbie to shell programming)I understand that ?
> Y=;while read -d\* ;do [ $Y ]&&echo "$REPLY"&&Y=||Y=1;done
(note that it is non-standard and the behavior varies amongst
the shells that support read -d (zsh, ksh93 and bash)).
It is actually very complicated.
The "read -d\*" is a command that returns true (with a zero exit
status) if it finds an unescaped "*" in its standard input.
It will store in the $REPLY variable the sequence of characters
read up to but not including that unescaped "*", but not before
having done a few transformations on it:
- except for bash, the leading and trailing blank characters
(space, tab or newline) will be removed as long as those blank
characters also happen to be present (once and only once for
zsh) in the $IFS special parameter or if $IFS is unset
- except for bash again, the escaped "*"s will be removed.
- The other "\x" escaped x characters will be changed to "x".
[ $Y ] is also very complicated.
It calls the "[" command with a number of arguments resulting
from the expansion of $Y and "]".
As $Y is not quoted, in all shells but zsh when not in sh/ksh
emulation, the expansion involves a very complex process. The
content of the $Y is first split according to the list of
characters contained in the $IFS special parameter (that part of
the process is generally called "word splitting"). The rules for
that vary from shell to shell, but with the default value of
$IFS, $Y will be considered as a list of blank separated words
(so, $Y will be split according to blanks and leading and
trailing blanks will be removed)
Then (again except with zsh), for those words, the shell will
attempt to consider each of them as a wildcard pattern and
expand them to a list of matching file names (relative to the
current directory) (that's the process generally called
"filename generation" or "globbing").
A last thing and that also applies to zsh, if the Y parameter is
empty, $Y will expand to no argument at all as opposed to one
empty argument (that's a process sometimes called "empties
removal").
Here, as it happens, the Y variable can only contain either
nothing or "1", so unless the $IFS character contains "1" $Y
will expand into either no argument at all or one argument being
"1".
The "[" command when called with the only 2 arguments "[" and
"]" is a command that returns "false" as a special case (no test
expression provided). "[" "1" "]" returns true on the ground
that "1" is not an empty string.
I think the OP's idea was to test whether the $Y string was
empty or not. So it was a very convoluted and dangerous way to
write [ -n "$Y" ] or [ "$Y" != "" ].
echo "$REPLY"
again, is a command whose behavior varies a lot between shell
and even for a same shell depending on the environment or the
way the shell was compiled.
That command will display the content of the $REPLY variable on
stdout followed by a newline character unless (depending on the
shell/echo implementation) $REPLY is one of "-" "-e", "-E",
"-n", "-ne", "-nn"... or contains backslash characters in which
case all sorts of things may happen.
So, that command is something that may do what you want in an
inefficient way probably for most inputs but will give
unexpected results (varying from shell to shell) for some other
inputs and is to my mind an improper usage of the shell.
--
Stéphane
|