On Fri, 19 Aug 2022 at 14:13, David Wright <deb...@lionunicorn.co.uk> wrote: > On Thu 18 Aug 2022 at 06:58:20 (-0400), Greg Wooledge wrote: > > On Wed, Aug 17, 2022 at 10:58:17PM -0500, David Wright wrote: > > > $ type soxy > > > soxy is a function > > > soxy () > > > { > > > [ -z "$1" ] && printf '%s\n' "Usage: ${FUNCNAME[0]} > > > path-to/sound-file-of-any-type [trim 20 2] > > > runs sox to play the file with any arguments given. > > > The example above reminds you to put the full argument." 1>&2 && > > > return 1; > > > local From="$1"; > > > shift; > > > sox -q "$From" -t alsa default "$@" > > > } > > > > Pedantic note: your error checking can fail. If the printf fails for > > some reason (e.g. because stderr has been closed, or is redirected to > > a file on a file system that's full), the return won't execute. > > True—I guess I was willing to carry the risk. Thanks for noting that. > > > It's best just to use "if" in the normal way: > > > > if [ -z "$1" ]; then > > printf ... > > return 1 > > fi > > > > That way, the return will still be executed even if the printf fails. > > > > If you *insist* on using && because you think it's tres chic or something, > > then you need to use a command group: > > > > [ -z "$1" ] && { > > printf ... > > return 1 > > } > > > > But this is not the recommended practice. > > Not so much très chic as bijou⁰. I can edit, eg > [ -z "$Thepagecount" ] && printf '%s\n' "$1 has no pages!" ¹>&2 && return 1 > to > [ -z "$Thepagecount" ] && { printf '%s\n' "$1 has no pages!" ¹>&2 ; return 1 > ; } > very easily. (I think I have about 350 such constructions in ~/.bash*.) > > The attraction of a one-liner is partly because of screens > being around four times wider than high (characterwise). > Wouldn't it be nice if bash had Perl's die ….
Hi David Some further bash script thoughts ... Considating hundreds of identical "printf '%s\n' 1>&2" constructs into one function seems like it would remove a lot of visual noise, and streamline reading and writing that code. My style would be: msg_stderr() { printf '%s\n' "$@" 1>&2 } soxy() { if [[ -z "$1" ]] ; then msg_stderr "Usage: ${FUNCNAME[0]} path-to/sound-file-of-any-type [trim 20 2] runs sox to play the file with any arguments given. The example above reminds you to put the full argument." return 1 fi } I find that style easier to read and reason about, but it would involve more editing of your existing code. Aside: I see that you are using ${FUNCNAME[0]}, so bash features are acceptable. Using an array to pass the message lines to the same function would preserve the code indentation, which further improves readability for me. soxy() { if [[ -z "$1" ]] ; then local m=( "Usage: ${FUNCNAME[0]} path-to/sound-file-of-any-type [trim 20 2]" "runs sox to play the file with any arguments given." "The example above reminds you to put the full argument." ) msg_stderr "${m[@]}" return 1 fi } If you want to stay close to the oneliner style that you already have, it could be done like this: die() { printf '%s\n' "$@" 1>&2 return 0 } soxy() { [[ -z "$1" ]] && die "message" && return 1 } This avoids the issue of unexpected errors in printf, makes all return values explicit, and avoids mixing && and || operators. And hopefully not much trouble for you to edit, either :)