Error message output
freebsd at edvax.de
Tue Sep 22 15:31:58 UTC 2020
On Mon, 21 Sep 2020 23:33:50 -0700, David Christensen wrote:
> On 2020-09-21 15:55, Polytropon wrote:
> > On Mon, 21 Sep 2020 15:33:40 -0700, David Christensen wrote:
> >> On 2020-09-21 04:21, Polytropon wrote:
> >>> On Sun, 20 Sep 2020 22:12:24 -0700, David Christensen wrote:
> >>>> On 2020-09-20 10:11, Polytropon wrote:
> >>>>> I have a general question. Is it still considered useful to
> >>>>> output error messages of a script to standard error?
> > Example (from a real script); the following normal usage
> > prints to standard output:
> > % png2pdf.sh mdcc_rg_2020-04-01
> > + mdcc_rg_2020-04-01_1.png
> > + mdcc_rg_2020-04-01_2.png
> > + mdcc_rg_2020-04-01_3.png
> > -> mdcc_rg_2020-04-01.pdf
> So, png2pdf.sh reads mdcc_rg_2020-04-01_1.png, mdcc_rg_2020-04-01_2.png,
> and mdcc_rg_2020-04-01_3.png, and writes mdcc_rg_2020-04-01.pdf?
Correct: You provide a "pattern" (i. e., "starts with", the shell
does the expansion of *), and the output file drops the "counter"
and is a PDF file containing the scanned sheets, so it's easier
to transfer and print. :-)
> I would drop the '.sh' extension.
Will do, especially as it's now in /opt/bin, a reason to be
> Providing a fractional base file name as an argument and computing input
> and output file names is unconventional. The FreeBSD convention seems
> to be to use complete file names for arguments. This allows the user to
> use shell globbing, find(1) and xargs(1), etc., or to wrap this script
> in another script that computes the arguments.
In this case, the calling shell would have to do it. I do not
expect csh or bash or zsh doing that differently from plain sh,
but you never know... :-)
> As this program operates on entire files and those files are binary, it
> is tempting to allow input file names on stdin. I think this idea is
> unconventional and better avoided.
Programs like cpio do this. Programs that operate on a set of
files typically get them via command line, while programs that
operate on _one_ file from a set of file often have their "list
generator" prefixed, like "something | xargs -n 1 progname".
> So, I'd go with positional arguments for the input and output file names.
> % png2pdf mdcc_rg_2020-04-01*.png mdcc_rg_2020-04-01.pdf
The key is that the output filename is "automatically" assigned
("base name without counter"). In such a case, I'd even go for
an optional argument for the output file, such as cc does:
% cc blah.c
generates a.out, but
% cc -o blah blah.c
generates blah as the output binary; -o is optional.
> When the argument list contains two (or more) kinds of things, it can be
> useful to pick one kind for arguments and to pass everything else via
> % png2pdf -O mdcc_rg_2020-04-01.pdf mdcc_rg_2020-04-01*.png
The advantage of having the invoking shell define the input files
is that it enables the user to combine files with different "base
names", such as:
% png2pdf -o report.pdf blah_01.png blah_02.png foo_*.png end.png
I think this is a good idea for further improvement.
Both concepts also work nicely with shell completition:
% png2pdf foo[TAB]
png2pdf foo_2020-01-23_ <adding>
In case there are no offending files of other types, "*" can
be the last symbol.
> My scripts emit '+' in the first position only when they have invoked
> sh(1) with xtrace enabled. Outputting '+' otherwise is confusing.
Never heared of that concept...
I thought it was good to use "+" for "adding", and "->" for "to
the result"; maybe "=" or even ":=" would have been possible too,
even though I tried hard to unlearn ":=". ;-)
> If I wanted to see the input file names as they were processed, I would
> add a verbose option and preface each input file name with "reading".
> The messages would to to stderr.
Or the opposite approach: -q (quiet) if you don't want those.
Or compare cp to cp -v.
> My similar scripts typically print (to stdout) the bare names of files
> and directories that they change. If there were multiple possibilities
> -- "writing", "appending", "creating", "updating", "deleting", etc. -- I
> would add prefaces. The messages would go to stdout.
> Messages for files that are not changed would be handled by verbose
> option messages -- "skipping", etc.. The messages would to to stderr.
> It is nice to have a quiet option suppresses all output except fatal
> error messages.
> For exit value, I use 0 for correct operation and 1 for everything else.
As suggested by sysexits.h, it's possible to signal the kind
of error to the caller. This is not standard in sh scripts,
but can be used there.
> > The typical error cases (input not found, no input specified)
> > output to standard error, and there is a non-zero exit code:
> > % png2pdf.sh nothing
> > Error: no matching source files for pattern nothing_*.png found, aborting.
> The FreeBSD convention seems to be to print the usage message when given
> bad options or arguments:
> Usage: png2pdf.sh [-v] [-q] infile... outfile
> png2pdf.sh [-v] [-q] [-O outfile] infile...
That is correct, and the system tools tend to follow that
convention. Existing man pages and the templates suggest
this style. Oh, and I should probably write a manpage, too. :-)
> > % png2pdf.sh
> > Convert PNG image files and create PDF
> > Usage: /opt/bin/png2pdf.sh <pattern>
> > The source file pattern must lead to files named <pattern>_*.png.
> > The target file's name will be <pattern>.pdf.
> When given no options or arguments, the FreeBSD convention seems to be
> to run the program with a default argument. If no default makes sense,
> then to print the usage message.
For the tool in question, the usage message would be the
default, as one cannot assume any valid input. :-)
Thank you for inspiration and further education. It's
always nice to learn something new or reconsider something
learned and / or long forgotten.
Happy FreeBSD user since 4.0
Andra moi ennepe, Mousa, ...
More information about the freebsd-questions