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:
> DESCRIPTION
> 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]
http://www.shellcheck.net/
Received on Tue Sep 06 2016 - 22:09:35 CEST