Unix Shell - Need help correcting this Bash function

This is Interesting: Free IT Magazines  
Home > Archive > Unix Shell > October 2004 > Need help correcting this Bash function





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Need help correcting this Bash function
Phil Powell

2004-10-08, 5:52 pm

# SYNTAX: delete_tar $folderPath $origFolderName $today
delete_tar()
{
echo "Are you sure you want to delete TAR file
""$1/${2}_${3}.tar.gz""? (Y/N Enter = N) "; read isOKDelete
if [ $isOKDelete = "Y" -o $isOKDelete = "y" ]; then
rm $1/${2}_${3}.tar.gz
fi
}


--------------------------------------------------------------------------------

I am very new to Bash Script (or Shell Script) and continually get the
"too many arguments" error on the "if" line if I do not enter either
"Y" or "y".

As dumb as this is going to sound, how must I do this correctly? I
have already gone to Linux Shell Script tutorials and apparently am
not grasping this.

Thanx
Phil
Tavis Ormandy

2004-10-08, 5:52 pm

On 2004-10-08, Phil Powell <phillip.s.powell@gmail.com> wrote:

> if [ $isOKDelete = "Y" -o $isOKDelete = "y" ]; then
> rm $1/${2}_${3}.tar.gz
> fi


>
> I am very new to Bash Script (or Shell Script) and continually get the
> "too many arguments" error on the "if" line if I do not enter either
> "Y" or "y".


If $isOKDelete is empty, it expands to

if [ = "Y" -o = "y" ]; then

>
> As dumb as this is going to sound, how must I do this correctly? I
> have already gone to Linux Shell Script tutorials and apparently am
> not grasping this.


Try quoting it, eg "$isOKDelete".

--
-------------------------------------
taviso@sdf.lonestar.org | finger me for my gpg key.
-------------------------------------------------------
Ed Morton

2004-10-08, 5:52 pm



Tavis Ormandy wrote:
> On 2004-10-08, Phil Powell <phillip.s.powell@gmail.com> wrote:
>
>
>
>
>
>
> If $isOKDelete is empty, it expands to
>
> if [ = "Y" -o = "y" ]; then
>
>
>
>
> Try quoting it, eg "$isOKDelete".
>


And put some other character in front of it to protect yourself from
someone entering an "odd" character like an exclamation mark (!):

if [ "X$isOKDelete" = "XY" ....

You might want to use a case statement for this so that if someone
enters "yes" instead of just "y", you can handle it, e.g.:

case $isOKDelete in
[yY]* ) rm $1/${2}_${3}.tar.gz ;;
esac

No need for the quotes, etc with a case statement:

----------------
PS1> x="!"; if [ "$x" = "y" ]; then echo success; fi
ksh: test: argument expected
PS1> x="!"; if [ "X$x" = "Xy" ]; then echo success; fi
PS1> x="y"; if [ "X$x" = "Xy" ]; then echo success; fi
success
PS1> x="!"; case $x in [yY]*) echo success;; esac
PS1> x="y"; case $x in [yY]*) echo success;; esac
success
-----------------

Regards,

Ed.
Tavis Ormandy

2004-10-08, 5:52 pm

On 2004-10-08, Ed Morton <morton@lsupcaemnt.com> wrote:
>
> And put some other character in front of it to protect yourself from
> someone entering an "odd" character like an exclamation mark (!):
>


protect from what? I don't think this is necessary.

> if [ "X$isOKDelete" = "XY" ....
>
> You might want to use a case statement for this so that if someone
> enters "yes" instead of just "y", you can handle it, e.g.:
>
> case $isOKDelete in
> [yY]* ) rm $1/${2}_${3}.tar.gz ;;
> esac


I'm not sure if a case construct is the most appropriate here, if can
handle this just as well, for example:

if [[ "$isOKDelete" = [yY]* ]]; then echo success; fi

--
-------------------------------------
taviso@sdf.lonestar.org | finger me for my gpg key.
-------------------------------------------------------
Ed Morton

2004-10-08, 5:52 pm



Tavis Ormandy wrote:
> On 2004-10-08, Ed Morton <morton@lsupcaemnt.com> wrote:
>
>
>
> protect from what? I don't think this is necessary.


Form what I showed in my examples - someone entering an unexpected
character like an exclamation mark. Here they are again:

PS1> x="!"; if [ "$x" = "y" ]; then echo success; fi
ksh: test: argument expected

PS1> x="!"; if [ "X$x" = "Xy" ]; then echo success; fi

It is necessary.

<snip>
> I'm not sure if a case construct is the most appropriate here, if can
> handle this just as well, for example:
>
> if [[ "$isOKDelete" = [yY]* ]]; then echo success; fi
>


That's fine too, but it's not as portable as a case statement and is a
bit longer to write:

if [[ "$isOKDelete" = [yY]* ]]; then echo success; fi
case $isOKDelete in [yY]*) echo success; esac

Regards,

Ed.
joe@invalid.address

2004-10-08, 5:52 pm

Ed Morton <morton@lsupcaemnt.com> writes:

> Tavis Ormandy wrote:
>
> Form what I showed in my examples - someone entering an unexpected
> character like an exclamation mark. Here they are again:
>
> PS1> x="!"; if [ "$x" = "y" ]; then echo success; fi
> ksh: test: argument expected
>
> PS1> x="!"; if [ "X$x" = "Xy" ]; then echo success; fi
>
> It is necessary.
>
> <snip>
>
> That's fine too, but it's not as portable as a case statement and is
> a bit longer to write:
>
> if [[ "$isOKDelete" = [yY]* ]]; then echo success; fi
> case $isOKDelete in [yY]*) echo success; esac


Then there's

[[ $isOKDelete = [yY]* ]] && echo success

Of course you're right that it's less portable than case, but once you
put #!/bin/ksh at the top of the script you've stopped worrying about
that :-)

Joe
--
Always drink upstream from the herd.
- Will Rogers
Tavis Ormandy

2004-10-08, 5:52 pm

On 2004-10-08, Ed Morton <morton@lsupcaemnt.com> wrote:
>
>
> Tavis Ormandy wrote:
>
> Form what I showed in my examples - someone entering an unexpected
> character like an exclamation mark. Here they are again:
>
> PS1> x="!"; if [ "$x" = "y" ]; then echo success; fi
> ksh: test: argument expected
>


OP clearly stated bash.

> PS1> x="!"; if [ "X$x" = "Xy" ]; then echo success; fi
>
> It is necessary.


Only if he decides to abandon bash and install whatever version of ksh
you have (it works fine in at&t ksh and pdksh here).

><snip>
>
> That's fine too, but it's not as portable as a case statement and is a
> bit longer to write:
>


If we all wrote code based on number of keystrokes, we wouldnt need an
ioccc.

> if [[ "$isOKDelete" = [yY]* ]]; then echo success; fi
> case $isOKDelete in [yY]*) echo success; esac


[[ "$isOKDelete" = [yY]* ]] && echo success ;)

--
-------------------------------------
taviso@sdf.lonestar.org | finger me for my gpg key.
-------------------------------------------------------
Ed Morton

2004-10-08, 5:52 pm



Tavis Ormandy wrote:

> On 2004-10-08, Ed Morton <morton@lsupcaemnt.com> wrote:
>
<snip>[vbcol=seagreen]
>
>
> OP clearly stated bash.


Yes and so he has a choice of being tightly coupled or loosely coupled
to that shells specific characteristics. As with any other programming,
loose coupling is best as long as it requires negligible additional
complexity and effort.

<snip>
>
>
> If we all wrote code based on number of keystrokes, we wouldnt need an
> ioccc.


My point was that specifying it as a case statement for the purposes of
portability didn't require any additional effort or complexity.

>
>
>
> [[ "$isOKDelete" = [yY]* ]] && echo success ;)


Again, not as portable and IMHO not as readable and not as easy to add
lines to and therefore not as easily maintainable as either the "if" or
the "case".

The solutions I posted will work in any Bourne-like shell and do not
require additional effort or add complexity compared to the alternatives
and are easier to enhance than some.

Ed.
Tavis Ormandy

2004-10-08, 5:52 pm

On 2004-10-08, Ed Morton <morton@lsupcaemnt.com> wrote:
>
>
> Tavis Ormandy wrote:
>
> Yes and so he has a choice of being tightly coupled or loosely coupled
> to that shells specific characteristics. As with any other programming,
> loose coupling is best as long as it requires negligible additional
> complexity and effort.


I completely agree, but in this case, working around your shell's quirks
does require additional complexity, effort, and knowledge of the
different shells in use, why should it be necessary?

>
> Again, not as portable and IMHO not as readable and not as easy to add
> lines to and therefore not as easily maintainable as either the "if" or
> the "case".


Maybe not as portable,

[[ "$isOKDelete" = [yY]* ]] && {
echo but you cant
echo add lines any
} || {
echo easier than this
}



> The solutions I posted will work in any Bourne-like shell and do not
> require additional effort or add complexity compared to the alternatives
> and are easier to enhance than some.
>
> Ed.


They may be historically compatible, but they sacrifice the useful features
in all modern shells designed to make enhancing your scripts easier.

--
-------------------------------------
taviso@sdf.lonestar.org | finger me for my gpg key.
-------------------------------------------------------
Chris F.A. Johnson

2004-10-08, 8:47 pm

On 2004-10-08, Tavis Ormandy wrote:
> On 2004-10-08, Ed Morton <morton@lsupcaemnt.com> wrote:
>
> I completely agree, but in this case, working around your shell's quirks
> does require additional complexity, effort, and knowledge of the
> different shells in use, why should it be necessary?


If you use a portable syntax, you don't have to worry about your
(or any other) shell's quirks.

If you find youself on a system which doesn't have your favourite
shell, and you do not have the option of installing it, it is
extra work to convert all the non-portable lines in your script.

If you use them only when the portable syntax cannot be used,
you'll find that most scripts need no massaging. Those that do
will only require workarounds for a few lines.

>
> Maybe not as portable,
>
> [[ "$isOKDelete" = [yY]* ]] && {
> echo but you cant
> echo add lines any
> } || {
> echo easier than this
> }
>
>
>
>
> They may be historically compatible, but they sacrifice the useful features
> in all modern shells designed to make enhancing your scripts easier.


What "useful features" are required in this instance?

When they _are_ necessary, by all means use them. When they
aren't, why limit portability?


--
Chris F.A. Johnson http://cfaj.freeshell.org/shell
========================================
===========================
My code (if any) in this post is copyright 2004, Chris F.A. Johnson
and may be copied under the terms of the GNU General Public License
Tavis Ormandy

2004-10-08, 8:47 pm

On 2004-10-08, Chris F.A. Johnson <cfajohnson@gmail.com> wrote:
> If you use a portable syntax, you don't have to worry about your
> (or any other) shell's quirks.


Of course you do, if you didnt have to worry about it, it wouldnt be a
quirk. For example, the single unix specification lists lots of examples
that should be valid but are broken in some antiquated implementation.

Not that this matters, the OP is writing a bash script!

> What "useful features" are required in this instance?
>


Pattern matching, as my example used. Parameter expansion could also be handy.

> When they _are_ necessary, by all means use them. When they
> aren't, why limit portability?


You're taking this out of context, I'm all for portability, but he's
writing a bash script, why not use the features that every modern shell
written in the last decade has and could genuinely be useful here?

--
-------------------------------------
taviso@sdf.lonestar.org | finger me for my gpg key.
-------------------------------------------------------
Chris F.A. Johnson

2004-10-08, 8:47 pm

On 2004-10-09, Tavis Ormandy wrote:
> On 2004-10-08, Chris F.A. Johnson <cfajohnson@gmail.com> wrote:
>
> Of course you do, if you didnt have to worry about it, it wouldnt be a
> quirk. For example, the single unix specification lists lots of examples
> that should be valid but are broken in some antiquated implementation.


The set of constructions that are valid in all reasonably
POSIX-compliant shells is adequate for more than 90% of scripts.

> Not that this matters, the OP is writing a bash script!
>
>
> Pattern matching, as my example used. Parameter expansion could also be handy.


Pattern matching is available with case; [[..]] is not necessary (I
have NEVER used it in a script).

All POSIX shells have the important parameter expansions.

>
> You're taking this out of context, I'm all for portability, but he's
> writing a bash script, why not use the features that every modern shell
> written in the last decade has and could genuinely be useful here?


I do use those which are POSIX-compliant and common to those
shells. I don't use those which are limited to one or two shells
unless it makes a significant difference to the task at hand
because as I said before, I might want to use the script on a
machine which doesn't have bash, and on which I cannot install it.

You do not gain anything by using the non-POSIX

[[ $x = x* ]] && echo YES

instead of

case $x in x*) echo YES esac

which will work in all Bourne-type shells.

If I had a case where [[...]] was the only efficient method, I'd
use it. I know those situations exist, but I haven't come across
one in practice.

--
Chris F.A. Johnson http://cfaj.freeshell.org/shell
========================================
===========================
My code (if any) in this post is copyright 2004, Chris F.A. Johnson
and may be copied under the terms of the GNU General Public License
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com