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

Reply via email to