Re: [dev] Shell style guide

From: Antenore Gatta <>
Date: Tue, 6 Sep 2016 22:12:37 +0200

My bad... Sorry for the mail format.

On 09/06/16 22:09, Antenore Gatta wrote:
> Hi Evan!
> Thanks for this, it's something I can finally be involved (at least I hope).
> On 09/06/16 20:35, Evan Gates wrote:
>> Shebang: Use #!/bin/sh and only use POSIX shell features. If you need
>> bash features use the proper shebang, either #!/path/to/bash or
>> #!/usr/bin/env bash
> I agree with Hiro, bourne is not bash and scripts should be written in
> bourne
> shell, not bash... Better, in clean, simple, old style, POSIX compliant
> shell.
> So, just #/bin/sh
> Whatever there is behind is the OS business to make it works like full
> POSIX shell.
> I write my personal scripts in bash >4.0 or zsh or ksh93, I write portable,
> correct scripts in sh.
> From man sh:
>> The sh utility is the standard command interpreter for the
> system. The
>> current version of sh is close to the IEEE Std 1003.1 (“POSIX.1”)
>> specification for the shell. It only supports features designated by
>> POSIX, plus a few Berkeley extensions. This man page is not
> intended to
>> be a tutorial nor a complete specification of the shell.
>> Extension: Do not give your script a .sh extension. An executable
>> script is defining a new command. Do you run ls.elf? Furthermore if
>> the script is later rewritten in a different language the extension is
>> now wrong. It is acceptable to have a script with a .sh extension in a
>> project as long as it is then stripped of the extension and made
>> executable during the build (just like a .c file would be). The
>> following rule already exists as a builtin inference rule in POSIX
>> make to do this:
>> .sh:
>> cp $< $_AT_
>> chmod a+x $_AT_
> I'm not completely agree about this.
> A shell script it's not an executable by itself, it's a plain text file,
> like a
> .c file.
> A script installed under /usr/bin (or whatever), yes, it'd be installed
> without
> extention, that's why you find often that make rule.
> Whan you take a look at a project knowing it's extention simplify
> finding out
> what that files are meant just looking at the extention.
>> Quoting: Quote all expansions/substitutions. e.g. always use "$foo"
>> and never use $foo. There are an extremely small number of acceptable
>> reasons to break this rule, e.g. $CFLAGS (note that some parts of the
>> grammar do not require quotes for safe expansion such as assignment
>> and case $var in, we should discuss what to require in these cases)
> In my opinion just always. It doesn't make sense having exceptions.
>> Storing Commands: Do not store commands in strings. This is what
>> functions are for. Storing complex commands in strings and trying to
>> execute or eval them is fragile and needlessly complex.
>> Command Substitution: Always use "$()", never use backticks. This
>> makes for easier nesting and fewer surprises. Remember these should
>> always be quoted.
> s/Storing Command/Substituting Commands/
> I'm agree but I wouldn't fix a rule about this... Just prefer $()
> Remember to quote whatever is inside the the substitute commands and
> that you can
> nest them:
> $(whatever "$foo" $(othercmd "$bar"))
>> Variable Names: By convention all cap names are reserved for internal
>> shell variables and environment variables. If your variable is not
>> exported to the environment for use by a child process it should not
>> be all caps. Lower case variables also greatly increase readability.
> I would also initialize variables in the beginning of the
> script/function, for
> readibility.
>> Errexit: Do not use set -e. It is a legacy feature that is broken by
>> design and includes many corner cases and gotchas. Check the result of
>> each command that can fail and exit if necessary.
>> Checking exit status: Do not run a command and then check against $?.
>> This is pointless. Instead check the exit status directly with if
>> cmd; then .... or by using a boolean operator such as cmd && ...
>> Do not parse ls: ls is a tool to view files in a human readable
>> format. Most often when someone tries to use the output of ls they
>> really just wanted a glob anyway.
>> Test: Do not use parens or boolean operators inside test expressions.
>> They are deprecated and useless. Instead of [ "$a" = foo -a "$b" = bar
>> ] use [ "$a" = foo ] && [ "$b" = bar ]
>> Echo and printf: Do not use echo if your input includes a variable or
>> backslash. There is no safe way to do so. Use printf and %s instead.
> Regarding Hiro' comment, the argument against echo is that it's often a
> shell
> builtin, therefore it may sometimes behave in a strange way.
> This is sometimes true, but printf is not safe as well from that point
> of view,
> as it's a builtin as well in most shells.
> In a pure, POSIX, bourne shell implementation printf its the same as the
> C printf
> function, so it's preferred for formatted output.
> In scripts where you just need to output text, or to easily list files,
> echo is
> fine.
> echo *
> echo /path/*/whatever/*sh # that is better and faster than "ls"
> echo "I'm right"
>> These cover the most common mistakes I see.
>> I would be happy to comb through suckless projects and submit patches
>> that at least fix broken/dangerous code and preferably style aspects
>> as well.
> A flame maybe, what do you think about shellcheck? [1]
> If it sucks (IMO it doesn't at all), do we need a suckless version.
> [1]
Received on Tue Sep 06 2016 - 22:12:37 CEST

This archive was generated by hypermail 2.3.0 : Tue Sep 06 2016 - 22:24:12 CEST