On Mon, Jan 08, 2001 at 10:18:52PM -0800, Brad Doster <[EMAIL PROTECTED]> wrote:
| OK, just when you thought it was safe... <g>
| I have glob_dot_filenames set so that files beginning with "." are included.
Bear in mind that glob_dot_filenames's a bash-ism and won't work in
other Bourne shells...
| Here's one of the things I'm calling zap_word() from:
|
| flist=*
| for fname in $flist; do
| if [ -d "$fname" ]; then
| flist=`zap_word "$fname" "$flist"`
| fi
| done
| echo [flist]=[$flist]
|
| (Actually, I have a faster routine than the above that works fine, but I'm
| trying to understand why the above does|doesn't work depending on the
| following...)
|
| When zap_word() includes 'echo $2 ...', the above works fine (all
| directories including '.' and '..' are removed from flist). When I change
| that to 'echo "$2" ...', the result is '[flist]=[]'. Knowing that a .
| matches any single character, this makes some sense ('echo * | sed "s/ . /
| /' wipes out '*' in the first successful 'if' iteration).
|
| What's driving me nuts is that when I try to echo the 'echo' command in the
| function in order to _see_ what's happening, I get the same result with and
| without the quotes around $2, i.e. within the function...
Ah, grasshopper...
This is because you misunderstand when globbing occurs.
Globbing happens to command lines after parameter substitution.
In your script, $flist is a literal * because globbing doesn't happen
in assignment statements. The for loop interates over the expansion of
* because globbing happens to the "for" after parameter substitution.
So your:
for fname in $flist
becomes
for fname in *
and that then becomes
for fname in . .. .....etc
Likewise in your `zap_word ...` you're passing a literal * as $2 to the
function. In the function, which I'll recite here to preserve context:
zap_word() {
# Arguments: "word to delete" "word list to delete from"
echo "$2" | sed "s/^/ / ; s/\$/ / ; s/ $1 / / ; s/^ // ; s/ \$//"
}
You're thus echoing a plain * into the sed command. If you rip off the
quotes the * gets expanded for the echo statement and thus the same
list (". .. ....etc") is sent in as you'd expected.
That actual fix is to get $flist to have the expanded list instead of
a plain *, which you can do by changing
flist=*
into
flist=`ls -a`
With glob_dot_filenames active you could say
flist=`echo *`
but that's not portable to other Bourne shells, so I'll avoid it.
However, `ls -a` and `echo *` are subtly different. The former embeds
newlines in the string while the latter uses spaces. Watch:
ls -a | cat
echo * | cat
(The "| cat" is a trick: the original ls command printed filenames one
per line. Modern ls commands notice they're going to a terminal and
print in columns to ease the burden on the person, but retain the one
per line mode if the output isn't a terminal, which is normally what
you want in the unix world with pipelines. So piping through cat makes
stdout a pipe instead of a terminal, which makes ls behave the same way
it does in `` marks.)
This will actually cause trouble to your zap_words function because
echo "$2"
will happily produce $2 verbatim. Which means with newlines.
One the other hand, if you're gone this route to start with (one word
per line, which is The Usual UNIX Way - one line records to manipulate)
your zap_words could have been:
zap_word() {
sed "/^$1\$/d"
}
and you'd use it like this:
flist=`echo "$flist" | zap_word "$fname"`
In short, it looks like a command, and most UNIX commands operate as
filters so that's how we'll use it. Of course, then we'd lose the
chance to play space padding sed games...
BTW, if I wrote "gimme all the things in this dir which aren't dirs"
I'd probably say
flist=
for fname in `ls -a`
do [ -d "$fname" ] || flist="$flist $fname"
done
Not that your way is invalid. But mine's shorter and faster (it doesn't
invoke lots of copies of sed to do things).
Cheers,
--
Cameron Simpson, DoD#743 [EMAIL PROTECTED] http://www.zip.com.au/~cs/
It is seldom that liberty of any kind is lost all at once. - Hume
_______________________________________________
Redhat-list mailing list
[EMAIL PROTECTED]
https://listman.redhat.com/mailman/listinfo/redhat-list