You are not logged in.

#1 2020-06-29 17:14:46

assertion9
Banned
Registered: 2019-04-13
Posts: 50

[SOLVED] Need guidelines about writing POSIX compliant shell scripts

I recently started to write some scripts and I wonder whether my approach is correct or not in terms of style and how I do common things like executing command as a string.

For example, the following script uses rsync to create backup of my dotfiles. Clearly I avoided such bashism like brace expansion, with the use of which I could specify my backup files and folders like "--include={.bashrc,.bash_profile..}". Instead I used an array and loop for achieving the same goal. Also as a final command of backup I use eval on a string, so at first I create a string which contains the initial part of command and then in a loop I concatenate command string and finally execute it with eval.

#!/bin/sh

DOTFILES=(.bashrc .bash_profile .gitconfig .xinitrc .config/***)

cmd="rsync -aAX --delete-excluded"

for df in "${DOTFILES[@]}"; do
    cmd="${cmd} --include=$df"
done

cmd="${cmd} --exclude='*' /home/assertion9/ /run/media/assertion9/root"

eval $cmd

I would appreciate any critique on behalf of this script or how could I improve it further to make efficient. Also I've searched a lot to find any guidelines on writing posix complaint scripts and couldn't find any, please share some books or links for starters or where I could find some ready examples of posix shell scripts. Thank you.

Last edited by assertion9 (2020-06-29 18:05:55)

Offline

#2 2020-06-29 17:23:36

Scimmia
Fellow
Registered: 2012-09-01
Posts: 11,539

Re: [SOLVED] Need guidelines about writing POSIX compliant shell scripts

shellcheck.net

There are no such things as arrays in POSIX sh.

Offline

#3 2020-06-29 17:51:25

Head_on_a_Stick
Member
From: London
Registered: 2014-02-20
Posts: 7,732
Website

Re: [SOLVED] Need guidelines about writing POSIX compliant shell scripts

assertion9 wrote:

please share some books or links for starters

https://pubs.opengroup.org/onlinepubs/9 … hap02.html
https://www.grymoire.com/Unix/Sh.html
https://github.com/dylanaraps/pure-sh-bible
http://www.etalabs.net/sh_tricks.html

Scimmia wrote:

shellcheck.net

That's in the [community] repositories: https://www.archlinux.org/packages/comm … hellcheck/

I also like checkbashisms (lifted from Debian's devscripts package).

EDIT: and for POSIX "arrays" see https://github.com/krebs/array

EDIT2: note that /bin/sh in Arch is linked to bash by default (which is why your array worked) — it can be linked to dash instead, as Debian do: https://wiki.archlinux.org/index.php/Da … ng_/bin/sh

Last edited by Head_on_a_Stick (2020-06-29 18:07:14)

Offline

#4 2020-06-29 18:05:41

assertion9
Banned
Registered: 2019-04-13
Posts: 50

Re: [SOLVED] Need guidelines about writing POSIX compliant shell scripts

Head_on_a_Stick wrote:
assertion9 wrote:

please share some books or links for starters

https://pubs.opengroup.org/onlinepubs/9 … hap02.html
https://www.grymoire.com/Unix/Sh.html
https://github.com/dylanaraps/pure-sh-bible
http://www.etalabs.net/sh_tricks.html

Scimmia wrote:

shellcheck.net

That's in the [community] repositories: https://www.archlinux.org/packages/comm … hellcheck/

I also like checkbashisms (lifted from Debian's devscripts package).

EDIT: and for POSIX "arrays" see https://github.com/krebs/array

I really appreciate it, thank you

Offline

#5 2020-06-29 18:07:42

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,514
Website

Re: [SOLVED] Need guidelines about writing POSIX compliant shell scripts

No need for the loop, printf itself will loop through arguments:

DOTFILES='.bashrc .bash_profile .gitconfig .xinitrc .config/***'

cmd="rsync -aAx --delete-excluded"
cmd="$cmd $(printf ' --include=%s' $DOTFILES)"
cmd="$cmd --exclude='*' /home/assertion9/ /run/media/assertion9/root"

Of course I think you could rethink the whole approach.  There is a lot to know about good shell scripting, but in my book, the most important thing to understand is the component programs that you are stringing together in the script.  Use their built-in efficiencies rather than reinventing the wheel.  In this case, use rsync's '--include-from' parameter.  I can't check this locally to confirm that it will read from /dev/stdin for this parameter, but I'm pretty sure it would.  If not, this could be reworked to use a file descriptor or a temp file:

rsync -aAx --delete-excluded --include-from=/dev/sdin --exclude='*' /home/assertion9/ /run/media/assertion9/root <<'EOF'
.bashrc
.bash_profile
.gitconfig
.xinitrc
.config/***
EOF

On arrays, POSIX shells do have one array.  While I don't think it'd be a good use here, you could adjust your original approach to keep using the array and loop:

set -- .bashrc .bash_profile .gitconfig .xinitrc .config/***

cmd="rsync -aAX --delete-excluded"

for df in $@; do
   ...

And as a side note Thank You for taking an interested in making more portable shell scripts.  It's a passion of mine to advocate for broader portability where practical; there are goals for which features of a given shell (e.g., BASH) may really help, but there are lots of scripts that use bashisms for no real benefit, and neglect the portability costs.  This is particularly frustrating when the author isn't even aware of this and puts a /bin/sh shebang at the top.

Last edited by Trilby (2020-06-29 18:25:56)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#6 2020-06-29 18:23:28

assertion9
Banned
Registered: 2019-04-13
Posts: 50

Re: [SOLVED] Need guidelines about writing POSIX compliant shell scripts

Trilby wrote:

No need for the loop, printf itself will loop through arguments:

DOTFILES='.bashrc .bash_profile .gitconfig .xinitrc .config/***'

cmd="rsync -aAx --delete-excluded"
cmd="$cmd $(printf ' --include=%s' $DOTFILES)"
cmd="$cmd --exclude='*' /home/assertion9/ /run/media/assertion9/root"

Of course I think you could rethink the whole approach.  There is a lot to know about good shell scripting, but in my book, the most important thing to understand is the component programs that you are stringing together in the script.  Use their built-in efficiencies rather than reinventing the wheel.  In this case, use rsync's '--include-from' parameter.  I can't check this locally to confirm that it will read from /dev/stdin for this parameter, but I'm pretty sure it would.  If not, this could be reworked to use a file descriptor or a temp file:

rsync -aAx --delete-excluded --include-from=/dev/sdin --exclude='*' /home/assertion9/ /run/media/assertion9/root <<'EOF'
.bashrc
.bash_profile
.gitconfig
.xinitrc
.config/***
EOF

On arrays, POSIX shells do have one array.  While I don't think it'd be a good use here, you could adjust your original approach to keep using the array and loop:

set -- .bashrc .bash_profile .gitconfig .xinitrc .config/***

cmd="rsync -aAX --delete-excluded"

for df in $@; do
   ...

Got it, all three methods works flawlessly. Completely forgot that I could take advantage of heredoc. Thanks a lot

Offline

#7 2020-06-29 22:18:21

Scimmia
Fellow
Registered: 2012-09-01
Posts: 11,539

Re: [SOLVED] Need guidelines about writing POSIX compliant shell scripts

Head_on_a_Stick wrote:
Scimmia wrote:

shellcheck.net

That's in the [community] repositories: https://www.archlinux.org/packages/comm … hellcheck/

Sure, but have you tried installing it? Or keeping it up to date? Packaging haskell is not really sane.

Offline

#8 2020-06-29 22:48:49

Slithery
Administrator
From: Norfolk, UK
Registered: 2013-12-01
Posts: 5,776

Re: [SOLVED] Need guidelines about writing POSIX compliant shell scripts

Scimmia wrote:

Sure, but have you tried installing it? Or keeping it up to date? Packaging haskell is not really sane.

Which is exactly why I dropped it for shellcheck-bin. It was the only haskell package on my system and the daily hundreds of updates never sat well with me.


No, it didn't "fix" anything. It just shifted the brokeness one space to the right. - jasonwryan
Closing -- for deletion; Banning -- for muppetry. - jasonwryan

aur - dotfiles

Offline

#9 2020-06-30 03:29:24

bulletmark
Member
From: Brisbane, Australia
Registered: 2013-10-22
Posts: 652

Re: [SOLVED] Need guidelines about writing POSIX compliant shell scripts

Slithery wrote:

Which is exactly why I dropped it for shellcheck-bin. It was the only haskell package on my system and the daily hundreds of updates never sat well with me.

Me either. Thanks for the great tip.

Offline

Board footer

Powered by FluxBB