<<< Date Index >>>     <<< Thread Index >>>

Re: Reliable/safe way of removing empty maildirs?



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Thursday, December  6 at 03:31 PM, quoth Paul Hoffman:
>Or using backticks:
>
>    if [ "`find dir -type f`" ]; then
>
>I don't know if that's any more portable, though.

Backticks aren't any more portable, I don't think... but it doesn't 
matter too much. However the double-quotes there solve the problem 
that you note:

>Hmm, my test (builtin, bash 2.05b.0) can't be relied upon:
>
>                $ PS1='\n\$ '
>
>                $ mkdir foo; cd foo
>                /User/nkuitse/dt/foo
>
>                $ builtin test `find . -type f` || echo No files
>    OK    -->   No files

     $ builtin test "`find . -type f`" || echo No files
     No files

>                $ touch bar
>
>                $ builtin test `find . -type f` || echo No files
>    OK    --> 

     $ touch bar
     $ builtin test "`find . -type f`" || echo No files

>                $ touch baz
>
>                $ builtin test `find . -type f` || echo No files
>                bash: test: ./bar: unary operator expected
>    Oops! -->   No files

     $ touch baz
     $ builtin test "`find . -type f`" || echo No files

The reason for the problem is that the shell is evaluating things 
twice. In essence, the output of find is substituted for `find . -type 
f` in its raw form. You'd get the same problem if you did this:

     $ foo=""
     $ builtin test $foo && echo full || echo empty
     empty
     $ foo=one
     $ builtin test $foo && echo full || echo empty
     full
     $ foo="one two"
     $ builtin test $foo && echo full || echo empty
     -bash: test: one: unary operator expected
     empty

That last command is equivalent, to the shell, to the following 
command:

     $ builtin test one two && echo full || echo empty

In order to get the result you want, i.e. to test whether foo contains 
text, you have to quote it:

     $ builtin test "$foo" && echo full || echo empty

This specifies that no matter what's in foo, it's part of a single 
quoted string that is passed as the only argument to test.

The same thing is true of anything that the shell evaluates, including 
backtick expansion. In other words, the following two commands behave 
the same way:

     $ test $foo && echo full || echo empty
     $ test `echo $foo` && echo full || echo empty

... and they both have the same solution: encapsulate whatever it is 
inside quotes:

     $ test "$foo" && echo full || echo empty
     $ test "`echo $foo`" && echo full || echo empty

Heh, ain't the shell grand?

~Kyle
- -- 
Nonsense. Space is blue and birds fly through it.
                                                          -- Heisenberg
-----BEGIN PGP SIGNATURE-----
Comment: Thank you for using encryption!

iD8DBQFHWGUJBkIOoMqOI14RAt59AKCZOYtUjkEemFpLm2lZK1vr6XCmTgCcDEOe
w+PrVIPulkGo+xatxk5x8g4=
=m/9g
-----END PGP SIGNATURE-----