bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: select syntax violates the POLA


From: Robert Elz
Subject: Re: select syntax violates the POLA
Date: Thu, 01 Apr 2021 23:58:13 +0700

    Date:        Thu, 1 Apr 2021 11:36:14 -0400
    From:        Greg Wooledge <greg@wooledge.org>
    Message-ID:  <YGXobn5/DqMiuc44@wooledge.org>

  | On Thu, Apr 01, 2021 at 01:36:59AM -0700, greywolf@starwolf.com wrote:
  | >   The following is valid shell code:
  | > 
  | >   d=($(ls /usr/src/pkg/*/$1));
  |
  | Syntactically valid, but semantically wrong.

Greg managed to comment on everything in the original message, except
the actual point of it ... Chet answered that, so I won't bother,
but:

  | If $1 is not a directory, then you want:

It is a directory, or I'd guess, quite likely a pattern chosen
to find where the package that is wanted lives.  The '/*/' represents
a category grouping, and it is not unusual to not know which one applies
to any particular package.

My guess is that $1 might be something like *sed* to find any package
with "sed" in its name.  Or p5-* to select from the perl5 (script) packages.

So:
  | d=(/usr/src/pkg/*/"$1")

definitely not that, the quotes are wrong in any case (but apart from
that, if filename expansion happens in array assignments (it doesn't in
normal ones, and I dislike arrays, so ...) then without the quotes that
might work.

Alternatively
        d=( $( ls -d /usr/src/pkg/*/$1 ) )
or just
        d=( $( printf %s\\n /usr/src/pkg/*/$1 ) )

Just to be sure.    Personally I'd do

        set -- /usr/src/pkg/*/$1

and then simply use the positional parameters.

  | If $1 is supposed to be a directory, and therefore you want only filenames
  | and not full pathnames in the array,

It is, but he almost certainly wants the directory names, not the
contents of the directories.   He's going to want the full pathname
so once selected, he can cd to it.

  | >   cd ${dir} &&
  |
  | Quotes.

Yes.   But it turns out not to matter in this case, as none of
the names will ever contain anything but "normal" characters
(no spaces, newlines, asterisks, ...)

But that's the cd which requires dir to be the full pathname.

  | >   make clean && {
  | >       make update ||
  | >       make install;
  | >   }
  |
  | Is the inner || supposed to be && by chance?

Probably not.   This is "if the package is already
installed, update it, if not, install it".   "make update"
will succeed and update the package if needed, if it is installed
already, otherwise it will fail.  In that case make install
will install it (it would fail if a some other version of
the package was already installed).   (The preceding "make clean"
just gets rid of the left overs from any previous compilation,
but will fail if there's insufficient permission, or similar,
in which case attempting an update or install would also fail).

  | >   if ((n > 1)); then {
  | >       select dir in ${d[@]}; do {
  | >           break;
  | >       } done;
  | >   }
  |
  | "${d[@]}" with quotes.

Again, yes, but in practice here, not needed.

  | What purpose do the extra curly braces serve?

Good question, wondered that myself.   Note that if they were omitted
the odd syntax issue wouldn't have arisen, as the done would follow "break;"
and be recognised.

After all that, and ignoring select's syntax (it was invented by
ksh, long long ago, and isn't going to change) it is a dumb interface
that can always be coded better using other mechanisms.   And when you
do that you can allow for much more flexible input than just the line
number the select demands.

If you avoid select, and avoid arrays, then any Bourne style shell will work.
So, do that.

kre




reply via email to

[Prev in Thread] Current Thread [Next in Thread]