Sysop: | Amessyroom |
---|---|
Location: | Fayetteville, NC |
Users: | 43 |
Nodes: | 6 (0 / 6) |
Uptime: | 108:32:17 |
Calls: | 290 |
Files: | 905 |
Messages: | 76,683 |
For someone who is relatively new to Unix shell scripting (me) some
advice would be more than welcome on where to begin.
I have two main queries:
Q1) How can one write a script which is maximally compatible with
different systems?
I am thinking to write in /the language of/ the Bourne shell, if
feasible, so that it could be run by either the Bourne shell or Bash,
etc? (Ideally, the shebang line would be #!/bin/sh.)
Or is Bash now so universal that there's no point any longer in writing
for anything else?
Q2) How does one go about handling arguments in preferably a simple but universal way?
My first idea was to iterate over arguments with such as
while [ $# -gt 0 ]
do
...
shift
done;
and from that to (a) note any switches and (b) build up an array of positional parameters. However, I gather the Bourne shell has no arrays (other than the parameters themselves) so that won't work.
I read up on getopts
but from tests it seems to require that switches
precede arguments rather than allowing them to be specified after, so
that doesn't seem very good, either.
Online tutorials show different ways to handle this and few talk about
which shell to use for this case so I thought I would ask you guys for suggestions.
My requirement just now is, in fact, so simple that I don't need a
universal way to handle things but ISTM best to start with an approach
that will scale over time, if there is one.
So any guidance on how to get started would be appreciated!
On 15.04.2024 14:22, James Harris wrote:
I read up on getopts
It's the right tool.
but from tests it seems to require that switches
precede arguments rather than allowing them to be specified after, so
that doesn't seem very good, either.
That's the usual convention, first come the options (with optional arguments), then the non-option arguments. Here's a syntax example
yagol [-s] [-w width] [-h height] [-g[ngen]] [-d density]
[-i infile] [-o outfile] [-r random-seed] [-u rule]
[-k|-t[sec]|-l|-f] [-p|-n|-c] [-a[gen]] [-m[rate]]
Q1) How can one write a script which is maximally compatible with
different systems?
I am thinking to write in /the language of/ the Bourne shell, if
feasible, so that it could be run by either the Bourne shell or Bash,
etc? (Ideally, the shebang line would be #!/bin/sh.)
Q2) How does one go about handling arguments in preferably a simple but universal way?
I read up on getopts
but from tests it seems to require that switches precede arguments
rather than allowing them to be specified after, so that doesn't
seem very good, either.
For someone who is relatively new to Unix shell scripting (me) some
advice would be more than welcome on where to begin.
I have two main queries:
Q1) How can one write a script which is maximally compatible with
different systems?
Q2) How does one go about handling arguments in preferably a simple but universal way?
For someone who is relatively new to Unix shell scripting (me) some advice would be more than welcome on where to begin.
I have two main queries:
Q1) How can one write a script which is maximally compatible with different systems?
I am thinking to write in /the language of/ the Bourne shell, if feasible,
so that it could be run by either the Bourne shell or Bash, etc? (Ideally, the shebang line would be #!/bin/sh.)
Or is Bash now so universal that there's no point any longer in writing for anything else?
Q2) How does one go about handling arguments in preferably a simple but universal way?
My first idea was to iterate over arguments with such as
while [ $# -gt 0 ]
do
...
shift
done;
and from that to (a) note any switches and (b) build up an array of positional parameters. However, I gather the Bourne shell has no arrays (other than the parameters themselves) so that won't work.
I read up on getopts but from tests it seems to require that switches
precede arguments rather than allowing them to be specified after, so that doesn't seem very good, either.
As others have said, write your script to the POSIX shell language
standards.
Then, there is getopts (which is /not/ a universally-supported extension
to the shell language),
In article <slrnv1qib9.1f89.naddy@lorvorc.mips.inka.de>,
Christian Weisgerber <naddy@mips.inka.de> wrote:
On 2024-04-15, Lew Pitcher <lew.pitcher@digitalfreehold.ca> wrote:
As others have said, write your script to the POSIX shell language
standards.
Then, there is getopts (which is /not/ a universally-supported extension >>> to the shell language),
It is part of POSIX sh.
It would be useful to know exactly *why* OP wants to stay "as portable as possible". Yes, I know it is against the creed here to question such
things, but it needs to be done, nevertheless.
I say this as someone who does occasionally program in dash (Debian's
version of the "POSIX shell" paradigm), just to see and to remind myself about how limited it is. But I would urge OP to think long and hard about whether or not it matters. I find that when I do program in dash, I rather quickly run into the limitations and end up regretting the choice.
On 2024-04-15, Lew Pitcher <lew.pitcher@digitalfreehold.ca> wrote:
As others have said, write your script to the POSIX shell language
standards.
Then, there is getopts (which is /not/ a universally-supported extension
to the shell language),
It is part of POSIX sh.
On 2024-04-15, Lew Pitcher <lew.pitcher@digitalfreehold.ca> wrote:
As others have said, write your script to the POSIX shell language
standards.
Then, there is getopts (which is /not/ a universally-supported extension
to the shell language),
It is part of POSIX sh.
On 2024-04-15, James Harris <james.harris.1@gmail.com> wrote:
Q1) How can one write a script which is maximally compatible
with different systems?
I am thinking to write in /the language of/ the Bourne shell,
if feasible, so that it could be run by either the Bourne shell
or Bash, etc? (Ideally, the shebang line would be #!/bin/sh.)
Yes. POSIX shell, more specifically. That is the easy part. The
difficult part is that your script will likely call various external
commands and those have a lot of variation as well.
Q2) How does one go about handling arguments in preferably a
simple but universal way?
That's too vague...
I read up on getopts
If you want to handle option flags, getopts is the way to go.
but from tests it seems to require that switches precede
arguments rather than allowing them to be specified after, so
that doesn't seem very good, either.
But that's the way Unix commands work. You cannot specify flags
after the first non-flag argument.
$ touch foo -l
$ ls foo -l
-l foo
$ ls -l foo -l
-rw-r--r-- 1 naddy naddy 0 Apr 15 15:28 -l
-rw-r--r-- 1 naddy naddy 0 Apr 15 15:28 foo
Apparently GNU implementations deviate from this, which makes for
a bad surprise and is incompatible with other implementations as
well as historical practice.
I read up on getopts but from tests it seems to require that
switches precede arguments
rather than allowing them to be specified after, so that doesn't
seem very good, either.
I am thinking to write in /the language of/ the Bourne shell, if
feasible, so that it could be run by either the Bourne shell or Bash,
etc? (Ideally, the shebang line would be #!/bin/sh.)
Or is Bash now so universal that there's no point any longer in writing
for anything else?
I read up on getopts but from tests it seems to require that switches
precede arguments rather than allowing them to be specified after, so
that doesn't seem very good, either.
Compare (using GNU ls) with Christians well‐behaving "ls":
touch -- foo -l
$ ls foo -l
-rw------- 1 helmut helmut 0 Apr 15 15:28 foo
Bash has an option that tells it to (attempt to) restrict itself to
POSIX semantics:
Starting Bash with the '--posix' command-line option or executing
'set -o posix' while Bash is running will cause Bash to conform more
closely to the POSIX standard by changing the behavior to match that
specified by POSIX in areas where the Bash default differs.
I haven't used this option myself, and I don't know just how closely it actually conforms to POSIX.
I'm less familiar with ksh and zsh, but they probably have similar
options. At least the "MirBSD Korn shell" has "set -o posix".
Bash has an option that tells it to (attempt to) restrict itself to
POSIX semantics:
Starting Bash with the '--posix' command-line option or executing^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'set -o posix' while Bash is running will cause Bash to conform more
closely to the POSIX standard by changing the behavior to match that
specified by POSIX in areas where the Bash default differs.
Christian Weisgerber <naddy@mips.inka.de> writes:
On 2024-04-15, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
Bash has an option that tells it to (attempt to) restrict itself to
POSIX semantics:
No, it does not:
Starting Bash with the '--posix' command-line option or executing^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'set -o posix' while Bash is running will cause Bash to conform more >>> closely to the POSIX standard by changing the behavior to match that >>> specified by POSIX in areas where the Bash default differs.
This only tweaks bash's behavior where it otherwise differs from
POSIX. It does not disable the myriad extensions.
I stand corrected.
On 2024-04-15, Helmut Waitzmann <nn.throttle@xoxy.net> wrote:
Compare (using GNU ls) with Christians well‐behaving "ls":
touch -- foo -l
$ ls foo -l
-rw------- 1 helmut helmut 0 Apr 15 15:28 foo
touch deviates in the first place; omit the -- and you get
$ touch foo -l
touch: invalid option -- 'l'
That's crazy. foo is a non-option argument, so the options
have ended at that point.
I see where it is documented in "2 Common options" (Coreutils
manual):
Normally options and operands can appear in any order, and
programs act as if all the options appear before any operands.
For example, ‘sort -r passwd -t :’ acts like ‘sort -r -t :
passwd’, since ‘:’ is an option-argument of -t. However, if
the POSIXLY_CORRECT environment variable is set, options must
appear before operands, unless otherwise specified for a
particular command.
It is disingenous to call it "POSIXly correct", because in fact
the POSIX rules are how everyone understands it and how other
implementors of utilities implement it. (Does anyone else do
this crazy thing?)
If all the vendors feature a given extension, so that it is
portable, but POSIX refuses to adopt it, then, sure: the mode
which takes the extension away can be flippantly called "POSIXly
correct".
Also the claim "options must appear before operands [in POSIX]"
is misleading, because "must" is usually interpreted as an
imposed requirement, which can be violated and diagnosed. But in
fact it is *logically* impossible for options to appear
elsewhere because arguments that look like options placed in the
non-option part of the command line are operands. It's the
logical "must", not the reuqirements "must".
On 2024-04-15, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
Bash has an option that tells it to (attempt to) restrict itself to
POSIX semantics:
No, it does not:
Starting Bash with the '--posix' command-line option or executing^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'set -o posix' while Bash is running will cause Bash to conform more
closely to the POSIX standard by changing the behavior to match that
specified by POSIX in areas where the Bash default differs.
This only tweaks bash's behavior where it otherwise differs from
POSIX. It does not disable the myriad extensions.
ISTR (which is to say, I can't prove it or point to an example at the moment), that there were some systems under some circumstances where if
bash was copied/linked as "sh" (and then run as "sh" instead of "bash"),
then it did indeed behave like a plain "POSIX" shell (i.e., extensions were disabled).
On 2024-04-15, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
There is a tool ...
... ShellCheck that among other things can be used to warn
about unportable code in shell scripts. https://www.shellcheck.net/
On Tue, 16 Apr 2024 11:11:16 -0000 (UTC), Christian Weisgerber wrote:
On 2024-04-15, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
There is a tool ...
Or just use a basic POSIX shell. Such things exist, you know.
... ShellCheck that among other things can be used to warn
about unportable code in shell scripts. https://www.shellcheck.net/
I dont see any mention of unportability, only about bugs.
Just for fun, I tried this:...
I would have to count every single one of those messages as spurious.
... ShellCheck that among other things can be used to warn
about unportable code in shell scripts. https://www.shellcheck.net/
I don’t see any mention of “unportability”, only about “bugs”.