TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Shell script best practices, from a decade of scripting things

958 pointsby sharat87over 2 years ago

101 comments

xelxebarover 2 years ago
Hands down, shell scripting is one of my all time favorite languages. It gets tons of hate, e.g. &quot;If you have to write more than 10 lines, then use a <i>real</i> language,&quot; but I feel like those assertions are more socially-founded opinions than technically-backed arguments.<p>My basic thesis is that Shell as a programming language---with it&#x27;s dynamic scope, focus on line-oriented text, and pipelines---is simply a different programming paradigm than languages like Perl, Python, whatever.<p>Obviously, if your mental model is BASIC and you try to write Python, then you encounter lots of friction and it&#x27;s easy for the latter to feel hacky, bad and ugly. To enjoy and program Python well, it&#x27;s probably best to shift your mental model. The same goes for Shell.<p>What is the Shell paradigm? I would argue that it&#x27;s line-oriented pipelines. There is a ton to unpack in that, but a huge example where I see friction is overuse of variables in scripts. Trying to stuff data inside variables, with shell&#x27;s paucity of data types is a recipe for irritation. However, if you instead organize all your data in a format that&#x27;s sympathetic to line-oriented processing on stdin-stdout, then shell will work with you instead of against.<p>&#x2F;2cents
评论 #33356574 未加载
评论 #33356766 未加载
评论 #33356477 未加载
评论 #33356383 未加载
评论 #33357704 未加载
评论 #33357102 未加载
评论 #33363061 未加载
评论 #33356504 未加载
评论 #33358256 未加载
评论 #33356502 未加载
评论 #33357605 未加载
评论 #33363634 未加载
评论 #33368209 未加载
评论 #33357462 未加载
评论 #33357341 未加载
评论 #33360106 未加载
评论 #33357060 未加载
评论 #33356440 未加载
评论 #33382088 未加载
评论 #33361843 未加载
评论 #33361976 未加载
评论 #33360961 未加载
评论 #33358751 未加载
评论 #33381785 未加载
评论 #33358859 未加载
Beltalowdaover 2 years ago
&gt; Use bash. Using zsh or fish or any other, will make it hard for others to understand &#x2F; collaborate. Among all shells, bash strikes a good balance between portability and DX.<p>I think fish is quite a bit different in terms of syntax and semantics (I&#x27;m not very familiar with it), but zsh is essentially the same as bash except without most of the needless footguns and awkwardness. zsh also has many more advanced features, which you don&#x27;t need to use (and many people are unaware of them anyway), but will very quickly become useful; in bash all sorts of things require obscure incantations and&#x2F;or shell pipelines that almost make APL seem obvious in comparison.<p>In my experience few people understand bash (or POSIX sh) in the first place, partly because everything is so difficult and full of caveats. Half my professional shell scripting experience on the job is fixing other people&#x27;s scripts. So might as well use something that doesn&#x27;t accidentally introduce bugs every other line.<p>Most – though obviously far from all – scripts tend to be run in environments you control; portability is often overrated and not all that important (except when it is of course). Once upon a time I insisted on POSIX sh, and then I realised that actually, &gt;90% of the scripts I wrote were run just by me or run only in an environment otherwise under my control, and that it made no sense. I still use POSIX sh for some public things I write, when it makes sense, but that&#x27;s fairly rare.<p>I think bash is really standing in the way of progress, whether that progress is in the form of fish, zsh, oil shell, or something else, because so many people conflate &quot;shell&quot; with &quot;bash&quot;, similar to how people conflate &quot;Google&quot; with &quot;search&quot; or &quot;git&quot; with &quot;GitHub&quot; (to some degree).
评论 #33356113 未加载
评论 #33354916 未加载
评论 #33354906 未加载
评论 #33356063 未加载
评论 #33356808 未加载
评论 #33355023 未加载
评论 #33354954 未加载
评论 #33356496 未加载
评论 #33356108 未加载
评论 #33355503 未加载
评论 #33355348 未加载
selectnullover 2 years ago
&gt; Use the .sh (or .bash) extension for your file. It may be fancy to not have an extension for your script, but unless your case explicitly depends on it, you’re probably just trying to do clever stuff. Clever stuff are hard to understand.<p>I don&#x27;t agree with this one. When I name my script without extension (btw, .sh is fine, .bash is ugly) I want my script to look just like any other command: as a user I do not care what the language program is written in, I care about its output and what it does.<p>When I develop a script, I get the correct syntax highlight becuase of the shebang so the extension doesn&#x27;t matter.<p>The rest of the post is great.
评论 #33354966 未加载
评论 #33355117 未加载
评论 #33355191 未加载
评论 #33355608 未加载
评论 #33356825 未加载
评论 #33358002 未加载
评论 #33355140 未加载
throwawaaarrghover 2 years ago
<i>&quot;Use set -o errexit&quot;</i><p>Only if it doesn&#x27;t matter that the script fails non-gracefully. Some scripts are better to either have explicit error handling code, or simply never fail. In particular, scripts you source into your shell should not use <i>set</i> options to change the shell&#x27;s default behavior.<p><i>&quot;Prefer to use set -o nounset.&quot;</i><p>ALWAYS use this option. You can test for a variable that might not be set with &quot;${FOO:-}&quot;. There is no real downside.<p><i>&quot;Use set -o pipefail.&quot;</i><p>Waste of time. You will spend so much time debugging your app from random pipe failures that actually didn&#x27;t matter. Dont use this option; just check the output of the pipe for sane values.<p><i>&quot;Use [[ ]] for conditions&quot;</i><p>No!!! Only use that for bashisms where there&#x27;s no POSIX alternative and try to avoid them wherever possible. YAGNI!<p><i>&quot;Use cd &quot;$(dirname &quot;$0&quot;)&quot;&quot;</i><p>Use either &quot;$(dirname &quot;${BASH_SOURCE[0]}&quot;)&quot; or grab a POSIX readfile-f implementation.<p><i>&quot;Use shellcheck.&quot;</i><p>This should have been Best Practice #1. You will learn more about scripting from shellcheck than 10 years worth of blog posts. Always use shellcheck. Always.<p>Also, don&#x27;t use <i>set -o nounset</i> when <i>set -u</i> will do. Always avoid doing something &quot;fancy&quot; with a Bashism if there&#x27;s a simpler POSIX way. The whole point of scripts is for them to be dead simple.
评论 #33358647 未加载
评论 #33357482 未加载
评论 #33357445 未加载
评论 #33364397 未加载
评论 #33358203 未加载
评论 #33357429 未加载
suprjamiover 2 years ago
Use a linter.<p>Pass all scripts through <a href="https:&#x2F;&#x2F;www.shellcheck.net&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.shellcheck.net&#x2F;</a> or use `shellcheck` on the commandline.<p>Learn the things it tells you and implement them in future scripts.
评论 #33355563 未加载
评论 #33355536 未加载
评论 #33355419 未加载
Xophmeisterover 2 years ago
There&#x27;s a bug in his template.<p>He suggests to `set -eu`, which is a good idea, but then immediately does this:<p><pre><code> if [[ &quot;$1&quot; =~ ^-*h(elp)?$ ]]; ... </code></pre> If the script is given no arguments, this will exit with an unbound variable error. Instead, you want something like this:<p><pre><code> if [[ &quot;${1-}&quot; =~ ^-*h(elp)?$ ]]; then</code></pre>
评论 #33355853 未加载
xelxebarover 2 years ago
&gt; set -o errexit<p>Unfortunately, `errexit` is fairly subtle. For example<p><pre><code> [ &quot;${some_var-}&quot; ] &amp;&amp; do_something </code></pre> is a standard way to `do_something` only when `some_var` is empty. With `errexit`, naively, this should fail, since `false &amp;&amp; anything` is always false. However, `errexit` in later versions of Bash (and dash?) ignore this case, since the idiom is nice.<p>However! If that&#x27;s the last line of a function, then the function&#x27;s return code will inherit the exit code of that line, meaning that<p><pre><code> f(){ [ &quot;${some_var-}&quot; ] &amp;&amp; do_something;}; f </code></pre> will actually trigger `errexit` when `some_var` is empty, despite the code being functionally equivalent to the above, non-wrapped call.<p>Anyway, there are a few subtleties like this that are worth being aware of. This is a good, but dated, reference: <a href="https:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;BashFAQ&#x2F;105" rel="nofollow">https:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;BashFAQ&#x2F;105</a>
ndsipa_pomuover 2 years ago
I&#x27;m not convinced about having shell scripts end with &quot;.sh&quot; as you may be writing a simple command style script and shouldn&#x27;t have to know or worry about what language it&#x27;s using.<p>I&#x27;m a fan of using BASH3 boilerplate: <a href="https:&#x2F;&#x2F;bash3boilerplate.sh&#x2F;" rel="nofollow">https:&#x2F;&#x2F;bash3boilerplate.sh&#x2F;</a><p>It&#x27;s standalone, so you just start a script using it as a template and delete bits that you don&#x27;t want. To my mind, the best feature is having consistent logging functions, so you&#x27;re encouraged to put in lots of debug commands to output variable contents and when you change LOG_LEVEL, all the extraneous info doesn&#x27;t get shown so there&#x27;s no need to remove debug statements at all.<p>The other advantage is the option parsing, although I don&#x27;t like the way that options have to have a short option (e.g. -a) - I&#x27;d prefer to just use long options.
评论 #33356170 未加载
评论 #33356255 未加载
rgrauover 2 years ago
&gt; If appropriate, change to the script’s directory close to the start of the script.<p>&gt; And it’s usually always appropriate.<p>I wouldn&#x27;t think so. You don&#x27;t know where your script will be called from, and many times the parameters to the script are file paths, which are relative to the caller&#x27;s path. So you usually don&#x27;t want to do it.<p>I collected many tips&amp;tricks from my experience with shell scripts that you may also find useful: <a href="https:&#x2F;&#x2F;raimonster.com&#x2F;scripting-field-guide&#x2F;" rel="nofollow">https:&#x2F;&#x2F;raimonster.com&#x2F;scripting-field-guide&#x2F;</a>
评论 #33355092 未加载
评论 #33354999 未加载
bluetomcatover 2 years ago
Use the shell only if your script is mostly about calling other programs and filtering and redirecting their output. That&#x27;s what the syntax of these languages is optimised for. As soon as you need any data manipulation (i.e. arrays, computation, etc.) it becomes a pain and Python is the much better fit.
评论 #33355266 未加载
评论 #33355382 未加载
评论 #33355279 未加载
jphover 2 years ago
I favor POSIX and dash over bash, because POSIX is more portable.<p>If a shell script needs any kind of functionality beyond POSIX, then that&#x27;s a good time to upgrade to a higher-structure programming language.<p>Here&#x27;s my related list of shell script tactics:<p><a href="http:&#x2F;&#x2F;github.com&#x2F;sixarm&#x2F;unix-shell-script-tactics" rel="nofollow">http:&#x2F;&#x2F;github.com&#x2F;sixarm&#x2F;unix-shell-script-tactics</a>
评论 #33354833 未加载
评论 #33357280 未加载
评论 #33355406 未加载
评论 #33356900 未加载
评论 #33355328 未加载
lhoursquentinover 2 years ago
&gt; [[ ]] is a bash builtin, and is more powerful than [ ] or test.<p>Agreed on the powerful bit, however [[ ]] is not a &quot;builtin&quot; (whereas [ and test are builtins in bash), it&#x27;s a reserved word which is more similar to if and while.<p>That why [[ ]] can break some rules that builtins cannot, such as `[[ 1 = 1 &amp;&amp; 2 = 2 ]]` (vs `[ 1 = 1 ] &amp;&amp; [ 2 = 2]` or `[ 1 = 1 -a 2 = 2 ]`, -a being deprecated).<p>Builtins should be considered as common commands (like ls or xargs) since they cannot bypass some fundamental shell parsing rules (assignment builtins being an exception), the main advantages of being a builtin being speed (no fork needed) and access to the current shell process env (e.g. read being able to assign a variable in the current process).
评论 #33366926 未加载
lockedinspaceover 2 years ago
This is not a best practices guide, please look forward to: <a href="https:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;BashGuide" rel="nofollow">https:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;BashGuide</a><p>For example, using cd &quot;$(dirname &quot;$0&quot;)&quot; to get the scripts location is not reliable, you could use a more sophisticated option such as: $(dirname $BASH_SOURCE)
评论 #33355470 未加载
评论 #33355151 未加载
评论 #33356908 未加载
评论 #33368586 未加载
belterover 2 years ago
Maybe the discussion should start at: Can you even do anything safely in Bash? - <a href="https:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;BashPitfalls" rel="nofollow">https:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;BashPitfalls</a>
评论 #33355635 未加载
评论 #33364325 未加载
bheadmasterover 2 years ago
&gt; For copy-paste: if [[ -n &quot;${TRACE-}&quot; ]]; then set -o xtrace; fi<p>&gt; People can now enable debug mode, by running your script as TRACE=1 .&#x2F;script.sh instead of .&#x2F;script.sh.<p>The above &quot;if&quot; condition will set xtrace even when user explicitly disables trace by setting TRACE=0.<p>A correct way of doing this would be:<p><pre><code> if [[ &quot;${TRACE-0}&quot; == &quot;1&quot; ]]; then set -o xtrace; fi</code></pre>
评论 #33355843 未加载
grumbelover 2 years ago
What would be the justification for &#x27;cd &quot;$(dirname &quot;$0&quot;)&quot;&#x27;? Going to the scripts directory does not seem very helpful. If I don&#x27;t care about the current directory, I might just go to &#x27;&#x2F;&#x27; or a temporary directory, when I do care about it I better stay in it or interpreting relative command line arguments is going to get difficult. When symbolic links are involved, dirname will also give the wrong directory.
评论 #33354900 未加载
评论 #33354881 未加载
评论 #33355977 未加载
评论 #33354815 未加载
ndsipa_pomuover 2 years ago
I think BASH scripting is the opposite of riding a bike - you end up re-learning it almost every time you need to do it
评论 #33364256 未加载
评论 #33356681 未加载
ghostoftiberover 2 years ago
Instead of implementing a -h or --help, consider using some code like &quot;if nothing else matches, display the help&quot;. The asterisk is for this purpose.<p><pre><code> while getopts :hvr:e: opt do case $opt in v) verbose=true ;; e) option_e=&quot;$OPTARG&quot; ;; r) option_r=&quot;$option_r $OPTARG&quot; ;; h) usage exit 1 ;; \*) echo &quot;Invalid option: -$OPTARG&quot; &gt;&amp;2 usage # call some echos to display docs or something... exit 2 ;; esac done</code></pre>
评论 #33366607 未加载
评论 #33360279 未加载
erlkonigover 2 years ago
Relying on errexit to save one from disaster is also often fatal, except for surpassingly simple scripts. While inside of <i>many</i> different kinds of control structures, the errexit is disabled, and usually just provides a false sense of security.<p>For someone who <i>knows</i> errexit can&#x27;t be trusted, and codes defensively anyway, it&#x27;s fine.
asicspover 2 years ago
See also:<p>* safe ways to do things in bash: <a href="https:&#x2F;&#x2F;github.com&#x2F;anordal&#x2F;shellharden&#x2F;blob&#x2F;master&#x2F;how_to_do_things_safely_in_bash.md" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;anordal&#x2F;shellharden&#x2F;blob&#x2F;master&#x2F;how_to_do...</a><p>* better scripting: <a href="https:&#x2F;&#x2F;robertmuth.blogspot.in&#x2F;2012&#x2F;08&#x2F;better-bash-scripting-in-15-minutes.html" rel="nofollow">https:&#x2F;&#x2F;robertmuth.blogspot.in&#x2F;2012&#x2F;08&#x2F;better-bash-scripting...</a><p>* robust scripting: <a href="https:&#x2F;&#x2F;www.davidpashley.com&#x2F;articles&#x2F;writing-robust-shell-scripts&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.davidpashley.com&#x2F;articles&#x2F;writing-robust-shell-s...</a>
评论 #33355069 未加载
chriswarboover 2 years ago
I agree with basically all of this. A few more:<p>The order of commandline args shouldn&#x27;t matter.<p>Env vars are better at passing key&#x2F;value inputs than commandline arguments are.<p>Process-substitution can often be used to avoid intermediate files, e.g. `diff some-file &lt;(some command)` rather than `some command &gt; temp; diff some-file temp`<p>If you&#x27;re making intermediate files, make a temp dir and `cd` into that<p>- Delete temp dirs using an exit trap (more reliable than e.g. putting it at the end of the script)<p>- It may be useful to copy `$PWD` into a variable before changing directory<p>Be aware of subshells and scope. For example, if we pipe into a loop, the loop is running in a sub-shell, and hence its state will be discarded afterwards:<p><pre><code> LINE_COUNT=0 some command | while read -r X do # This runs in a sub-shell; it inherits the initial LINE_COUNT from the parent, # but any mutations are limited to the sub-shell, will be discarded (( LINE_COUNT++ )) done echo &quot;$LINE_COUNT&quot; # This will echo &#x27;0&#x27;, since the incremented version was discarded </code></pre> Process-substitution can help with this, e.g.<p><pre><code> LINE_COUNT=0 while read -r X do # This runs in the main shell; its increments will remain afterwards (( LINE_COUNT++ )) done &lt; &lt;(some command) echo &quot;$LINE_COUNT&quot; # This will echo the number of lines outputted by &#x27;some command&#x27;</code></pre>
评论 #33356489 未加载
评论 #33356953 未加载
评论 #33355315 未加载
评论 #33355305 未加载
评论 #33355359 未加载
jstanleyover 2 years ago
Master Foo once said to a visiting programmer: “There is more Unix-nature in one line of shell script than there is in ten thousand lines of C.”<p>The programmer, who was very proud of his mastery of C, said: “How can this be? C is the language in which the very kernel of Unix is implemented!”<p>Master Foo replied: “That is so. Nevertheless, there is more Unix-nature in one line of shell script than there is in ten thousand lines of C.”<p>The programmer grew distressed. “But through the C language we experience the enlightenment of the Patriarch Ritchie! We become as one with the operating system and the machine, reaping matchless performance!”<p>Master Foo replied: “All that you say is true. But there is still more Unix-nature in one line of shell script than there is in ten thousand lines of C.”<p>The programmer scoffed at Master Foo and rose to depart. But Master Foo nodded to his student Nubi, who wrote a line of shell script on a nearby whiteboard, and said: “Master programmer, consider this pipeline. Implemented in pure C, would it not span ten thousand lines?”<p>The programmer muttered through his beard, contemplating what Nubi had written. Finally he agreed that it was so.<p>“And how many hours would you require to implement and debug that C program?” asked Nubi.<p>“Many,” admitted the visiting programmer. “But only a fool would spend the time to do that when so many more worthy tasks await him.”<p>“And who better understands the Unix-nature?” Master Foo asked. “Is it he who writes the ten thousand lines, or he who, perceiving the emptiness of the task, gains merit by not coding?”<p>Upon hearing this, the programmer was enlightened.<p>(<a href="https:&#x2F;&#x2F;catb.org&#x2F;~esr&#x2F;writings&#x2F;unix-koans&#x2F;" rel="nofollow">https:&#x2F;&#x2F;catb.org&#x2F;~esr&#x2F;writings&#x2F;unix-koans&#x2F;</a>)
emptyparadiseover 2 years ago
Personally I try to stick with POSIX sh (testing with dash), if I need anything fancier, I reach for Perl or Python.
评论 #33354622 未加载
hddqsbover 2 years ago
<i>&gt; Check if the first arg is `-h` or `--help` or `help` or just `h` or even `-help`, and in all these cases, print help text and exit.</i><p>`-h` and `--help` are fine. But `help` and `h` should only display the help if the script has subcommands (like `git`, which has `git commit` as a subcommand). Scripts that don&#x27;t have subcommands should treat `h` and `help` as regular arguments -- imagine if `cp h h.bak` displayed a help message instead of copying the file named &quot;h&quot;!<p>I wouldn&#x27;t encourage `-help` for displaying the help because it conflicts with the syntax for a group of single-letter options (though if `-h` displays the help, there is no legitimate reason for grouping `-h` with other options).<p>And ideally scripts that support both option and non-option arguments should allow `--` to separate them (e.g. `rm -- --help` removes the file called &quot;--help&quot;). But parsing options is complicated and probably out of scope for this article.<p><i>&gt; If appropriate, change to the script’s directory close to the start of the script. And it’s usually always appropriate.</i><p>This is very problematic if the script accepts paths as arguments, because the user would (rightly) expect paths to be interpreted relative to the original working directory rather than the script&#x27;s location. A more robust approach is to compute the script&#x27;s location and store it in a variable, then explicitly prepend this variable when you want paths to be relative to the script&#x27;s location.
IncRndover 2 years ago
There is an error with the template script on a fully patched m1 macbook. $1 is unbound, unless you provide an argument. This seems to be an utterly basic oversight for a template script from someone attempting to educate on bash&#x27;s best practices. Especially true for seeking a &quot;good balance between portability and DX&quot;.
评论 #33365108 未加载
gorgoilerover 2 years ago
Shell scripts are great for executing a series of commands with branching and looping logic around them.<p>As soon as output needs to be parsed — especially when it’s being fed back into other parts of the script — it gets harder. Handling errors and exceptions is even more difficult.<p>Things really fall down on modularity. There are tricks and conventions: for example you can put all functions to do with <i>x</i> in a file called <i>lib&#x2F;x.sh</i>, prefix them all with <i>x_</i>, and require that all positional parameters must be declared at the top of each function with local names.<p>At that point though, I would rather move to a language with named parameters, namespaced modules, and exception handling. In Python, it’s really easy to do the shell bits with:<p><pre><code> def sh(script): subprocess.run( [‘sh’, ‘-c’, script, ‘--‘, *args], check=True, ) </code></pre> which will let you pass in arguments with spaces and be able to access them as properly lexed arguments in $1, $2 etc in your script. You can even preprocess the <i>script</i> to be prefixed with all the usual <i>set -exuo pipefail</i> stuff etc.
HenrikBover 2 years ago
&gt; &quot;15. Use shellcheck. Heed its warnings.&quot;<p>(Disclaimer: I&#x27;m one of the authors)<p>After falling in love with ShellCheck several years ago, with the help of another person, I made the ShellCheck REPL tool for Bash:<p><pre><code> https:&#x2F;&#x2F;github.com&#x2F;HenrikBengtsson&#x2F;shellcheck-repl </code></pre> It runs ShellCheck on the commands you type at the Bash prompt as soon as you hit ENTER.<p>I found it to be an excellent way of learning about pit falls and best practices in Bash as you type, because it gives you instant feedback on possible mistakes. It won&#x27;t execute the command until the ShellCheck issues are fixed, e.g. missing quotes, use of undefined variables, or incorrect array syntax.<p>It&#x27;s designed to be flexible, e.g. you can configure ShellCheck rules to be ignored, and you can force executtion by adding two spaces at the end.<p>License: ISC (similar to MIT). Please help improve it by giving feedback, bug reports, feature requests, PRs, etc.
cduzzover 2 years ago
My biggest complaint about &quot;idiomatic&quot; shell scripting is the use of the [ and [[ operators. It gives the illusion that [ or [[ are part of the shell syntax when actually they&#x27;re just programs &#x2F; builtins &#x2F; functions which communicate with the rest of the script the same way (most) other things interact -- setting exit status. Specifically this means if .. then .. fi works with <i>any</i> program not just [ [[ operators.<p>Traditional shell might be:<p><pre><code> grep -q thing &lt; file if [ $? -eq 0 ] ; then echo &quot;thing is there ; fi </code></pre> VS just using if to look at the ES of the prior program<p><pre><code> if grep -q thing &lt; file then echo &quot;thing is there&quot; fi </code></pre> &quot;test&quot; and [[ are a fine programs &#x2F; tools for evaluating strings, looking at file system permissions, doing light math, but it isn&#x27;t the only way to interact with conditionals.
评论 #33367731 未加载
tonnydouradoover 2 years ago
I would add a &quot;zero&quot; best practice: don&#x27;t. If you&#x27;re thinking about writing enough shell script that it is worth putting it in a file, consider other languages or tools.<p>I&#x27;m not saying *never* write shell scripts, but always consider doing something else, or at least add a TODO, or issue, to write in a more robust language.
manv1over 2 years ago
Other tips for working with files:<p>always quote filenames, because you never know if there&#x27;s a space in them.<p>filenames with dashes or periods will kill you<p>prepend current directory file manipulation filenames with &quot;.&#x2F;&quot;, because the file might start with a period or dash<p>Dashes in filenames still might kill you, especially if you pass those to another command
moritonalover 2 years ago
If you are on Windows or Linux, Powershell is a decent scripting language that comfortably replaces Shell for scripted task running. The commands are vastly more readable and you get an okay experience with branches.<p>I&#x27;d also say that in most cases Python is also a better choice, especially when you use the ! syntax.
评论 #33355856 未加载
评论 #33365677 未加载
a1a1aover 2 years ago
One of my favorite shell script snippet is prepending timestamp to every output with the help of ts command of moreutils package, meanwhile write to log file at the same time: <a href="https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;questions&#x2F;26728&#x2F;prepending-a-timestamp-to-each-line-of-output-from-a-command" rel="nofollow">https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;questions&#x2F;26728&#x2F;prepending-a-...</a><p>exec &amp;&gt; &gt;( ts &#x27;[%Y-%m-%d.%H:%M:%S] &#x27; | tee ${LOGFILENAME} )
cpachover 2 years ago
For systems that I control myself I much prefer to avoid Bash&#x2F;sh. They’re just to clunky. And if I need to use them, I try to do as little as possible in order to make it more robust.<p>Case in point: Declaring an array. IMHO, it’s just not ergonomic at all. Especially not in sh&#x2F;dash.
oweilerover 2 years ago
Some things to add:<p>* use bats for testing * use shfmt for code formatting * use shellcheck for linting
gratonover 2 years ago
Author mentions using xtrace aka `set -x`. If using xtrace I highly recommend doing:<p><pre><code> export PS4=&#x27;+ ${BASH_SOURCE:-}:${FUNCNAME[0]:-}:L${LINENO:-}: &#x27; </code></pre> This will then append the filename, function name, and line number to the command being executed. Can make it much easier to find where exactly something is happening when working with larger bash scripts.
r3trohack3rover 2 years ago
One missing for me: when doing anything with numbers, use shell arithmetic $(()) and (()) instead of [[]] to be explicit: <a href="https:&#x2F;&#x2F;tldp.org&#x2F;LDP&#x2F;abs&#x2F;html&#x2F;arithexp.html" rel="nofollow">https:&#x2F;&#x2F;tldp.org&#x2F;LDP&#x2F;abs&#x2F;html&#x2F;arithexp.html</a>
woudsmaover 2 years ago
There is a VS Code extension[0] for Shellcheck that works just like ESLint. Very helpful when writing Bash scripts.<p>[0]: <a href="https:&#x2F;&#x2F;marketplace.visualstudio.com&#x2F;items?itemName=timonwong.shellcheck" rel="nofollow">https:&#x2F;&#x2F;marketplace.visualstudio.com&#x2F;items?itemName=timonwon...</a>
tuvi13over 2 years ago
I get my &quot;best practices&quot; from here: <a href="https:&#x2F;&#x2F;tldp.org&#x2F;LDP&#x2F;abs&#x2F;html&#x2F;index.html" rel="nofollow">https:&#x2F;&#x2F;tldp.org&#x2F;LDP&#x2F;abs&#x2F;html&#x2F;index.html</a><p>I think this site is amazing, and it must be older than at least two decades.
评论 #33361393 未加载
bcoughlanover 2 years ago
I&#x27;ve always had good results following &quot;Unofficial Bash Strict Mode&quot;: <a href="http:&#x2F;&#x2F;redsymbol.net&#x2F;articles&#x2F;unofficial-bash-strict-mode&#x2F;" rel="nofollow">http:&#x2F;&#x2F;redsymbol.net&#x2F;articles&#x2F;unofficial-bash-strict-mode&#x2F;</a>
Klasiasterover 2 years ago
Missing: When using &quot;set -o pipefail&quot; you should also catch any non-zero return codes that you want to accept, e.g., &quot;{ grep -o pattern file || true ; } | sed pattern&quot; to let the command continue (if desired) to execute even if pattern isn&#x27;t found.
pojzonover 2 years ago
Google Shell Guidelines are really good if someone is looking for good practice and clean code.
throwaway2037over 2 years ago
I&#x27;m surprised that no one mentioned a pair of tiny functions to log each command before it is run. Nicer versions also print a timestamp. Of course, this setup assumes: set -e<p><pre><code> echo_command() { echo echo &#x27;$&#x27; &quot;$@&quot; } echo_and_run_command() { echo_cmd &quot;$@&quot; &quot;$@&quot; } </code></pre> Then something like:<p><pre><code> main() { # For simple commands that do not use | &lt; &gt; etc. echo_and_run_command cp --verbose ... # More complex commands echo_command grep ... &#x27;|&#x27; find ... grep ... | find ... } main &quot;$@&quot;</code></pre>
评论 #33361477 未加载
评论 #33357207 未加载
deterministicover 2 years ago
My personal best practice for using shell scripts:<p>Don’t.<p>Use a proper programming language instead. bash (and similar scripting languages) are non-portable (Linux&#x2F;Windows) and the opposite of what I want in a good programming language.
eterevskyover 2 years ago
In my experience, the best practice is to implement all the non-trivial logic in the actual program or a Python script, and use shell script only for very straight-forward stuff like handling command-line arguments, environment variables and paths.
评论 #33355096 未加载
评论 #33355250 未加载
raydiatianover 2 years ago
Shell scripting feels like scripting in cursive. It’s obfuscatory (sed? curl? grep? ssssuper descriptive) for the sake of thinking about solving problems like the elder generation. To make matters worse, you’re not even doing hard computer science things most of the time. You’re tweaking bits in files, uploading&#x2F;downloading, searching, etc. It’s like having a butler who only understands your grocery list if it’s written in cursive.<p>I agree we need a shell scripting language, I disagree that bash zsh or anything that frequently uses double square brackets and awful program names is the epitome of shell scripting language design.
northisupover 2 years ago
does a mandalorian worry if another can wear their armor? no, its just for them.<p>giving up on the notion &quot;others will use or collaborate with my scripts&quot; was the single most productive thing i&#x27;ve done for my scripting.
评论 #33367722 未加载
frafraover 2 years ago
Define a cleanup function to nicely handle SIGTERM&#x2F;SIGKILL&#x2F;... maybe?
评论 #33355185 未加载
0xFEE1DEADover 2 years ago
&gt; Use set -o errexit at the start of your script. [...]<p>A couple of days ago this link was posted to hn <a href="http:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;BashFAQ&#x2F;105" rel="nofollow">http:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;BashFAQ&#x2F;105</a><p>It showed me once again how little bash I know even after all those years. I checked the examples to see if only set -e is dangerous or also set -o like the author suggested and sure enough it&#x27;s just as bad es set -e. You just got to thoroughly check your bash scripts and do proper error handling.
coliveiraover 2 years ago
I wrote a fair number of bash scripts, and the area where they&#x27;re definitely weaker than using a mainstream programming language is debugging. If something bad goes on a large script, it is not only harder to figure out why, but sometimes the error may be in one of a dozen native UNIX commands that have nothing to do with bash. The interaction between the shell and these UNIX commands is the weak point in the process and you can spend a long time trying to figure out what is really going on.
erlkonigover 2 years ago
No command should have an extension. And - quite notably - almost none do.<p>Adding an extension to make it easier to tell what&#x27;s inside without opening it is being lazy rather than following best practices. Best practice is half century of leaving them off.<p>Unlike Windows, which ignores extensions and lets you run a command omitting them, Unix has a better (I&#x27;m not saying perfect) approach which allow the metadata to pulled from the first line of the file, tuned <i>exactly</i> to what the script needs. No sane extension is going to capture this info well.<p>Extensions expose (usually incompletely) the implementation details of what&#x27;s inside, to the detriment of the humans using them (the OS doesn&#x27;t care), who will then guess at what the extension means.<p>However, many extensions are WRONG, or too vague to actually tell what interpreter to call on them - which this subgroup of devs does <i>all the time</i>, mostly commonly using the wrong version of python (wrong major, wrong minor, not from a specific python env) and breaking things. .sh is manifestly wrong as an extension for Bash scripts, which have different syntax.<p>The exception is scripts that should be &quot;.&quot;-ed in (sourced), where having a meaningful .sh or .bash (which are NOT interchangeable) is ACTUALLY good, because it highlights that they are NOT COMMANDS. (and execute isn&#x27;t enabled)<p>If you want a script to make it easier to list commands that are shell scripts or whatever, there&#x27;s a simple one at the end of:<p><a href="https:&#x2F;&#x2F;www.talisman.org&#x2F;~erlkonig&#x2F;documents&#x2F;commandname-extensions-considered-harmful&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.talisman.org&#x2F;~erlkonig&#x2F;documents&#x2F;commandname-ext...</a><p>I&#x27;ve seen several cases of .sh scripts which contained perl code, python, or were actually binary, because the final lynchpin in this (abridged) case against extensions is that in complex systems the extensions often have to be kept even after the implementation is upgraded to avoid breaking callers. It&#x27;s very normal for a program to start as shell, get upgraded to python, and sometimes again to something compiled. Setting up a situation which would force the extension to be changed in all clients in a large network to keep it accurate is beyond stupid.<p>Don&#x27;t use extensions on commands, and stop trying to rationalize it because you (for those to whom this applies) just like to do &quot;ls *.sh&quot; (on your bash scripts). These are a violation of Unix best practices, and cause harm when humans try to interpret them.
blobbersover 2 years ago
As someone who used to have to write a lot of shellscripts because I worked at a company that believed in files and not databases, if you want to get funky use:<p>shellcheck<p>It&#x27;s like pylint for your shellscripts.
评论 #33360351 未加载
pizza234over 2 years ago
A couple of other, important, settings:<p>- `set -o errtrace`: trap errors inside functions<p>- `shopt -s inherit_errexit`: subprocesses inherit exit error<p>Unfortunately the list of Bash pitfalls is neverending, but that&#x27;s a good start.
hun3over 2 years ago
&gt; 9. Always quote variable accesses with double-quotes. &gt; - One place where it’s okay not to is on the left-hand-side of an [[ ]] condition.<p>And the right-hand-side of a variable assignment.<p>And the WORD in a case statement. (Not in the patterns, though).<p>Plus a bunch of other single-token(?) contexts.<p>I don&#x27;t recommend relying on the context though, it&#x27;s clever and makes it hard to verify that the script does not have expansion bugs.
IYashaover 2 years ago
Mostly agree, but I add more.<p>1. end all your lines C-style; this may save your life many times;<p>2. declare -is variables and -r CONSTANTS at the beginning, again, C-style;<p>3. print TIMESTAMP=&quot;$(date +%Y-%m-%d\ %H:%M:%S)&quot;; where appropriate if your script logs its job;<p>4. Contrary to OPs reommendation I strongly try to stick to pure SH compatibility in smaller acripts so they can run on routers, TVs, androids and other busybox-like devices; BASH isn&#x27;t everywhere.
评论 #33359339 未加载
评论 #33355393 未加载
muth02446over 2 years ago
Also:<p><a href="http:&#x2F;&#x2F;robertmuth.blogspot.com&#x2F;2012&#x2F;08&#x2F;better-bash-scripting-in-15-minutes.html" rel="nofollow">http:&#x2F;&#x2F;robertmuth.blogspot.com&#x2F;2012&#x2F;08&#x2F;better-bash-scripting...</a><p><a href="https:&#x2F;&#x2F;google.github.io&#x2F;styleguide&#x2F;shellguide.html" rel="nofollow">https:&#x2F;&#x2F;google.github.io&#x2F;styleguide&#x2F;shellguide.html</a>
xwowsersxover 2 years ago
Can someone enlighten me on the<p><pre><code> cd &quot;$(dirname &quot;$0&quot;)&quot; </code></pre> part of this? This is changing to the directory of where the script is all cases?<p>EDIT: I should&#x27;ve just tested this to see :) I did and it does exactly that. Very helpful. I didn&#x27;t realize $0 is always the first argument. Kind of like how `self` is the first implicit argument in OOP methods?
rockyjover 2 years ago
Speaking of shell, which language do you think has the best interoperatibility with shell commands. I mean, running a command, parsing the output, looping, adding user interaction etc. with the least amount of friction. Ruby used to come close for me, just put the command in backticks `` and write the main logic in Ruby, but I want to hear if there is something better.
评论 #33363537 未加载
评论 #33354871 未加载
评论 #33355153 未加载
评论 #33355256 未加载
sharkenover 2 years ago
If someone could compile a similar list for PowerShell, that would be extremely helpful.<p>Kudos for nicely put tips that are easy to follow and understand.
webcaptchaover 2 years ago
Here is a template <a href="https:&#x2F;&#x2F;sharats.me&#x2F;posts&#x2F;shell-script-best-practices&#x2F;" rel="nofollow">https:&#x2F;&#x2F;sharats.me&#x2F;posts&#x2F;shell-script-best-practices&#x2F;</a> Should I put my code inside main()?<p>I&#x27;m newcomer in bash
baggiponteover 2 years ago
Nice, but for point 14 I would recommend using pushd&#x2F;popd instead of cd-ing directly into $0... any reasons to prefer cd directly?
评论 #33355515 未加载
评论 #33354811 未加载
drranover 2 years ago
Template in article is awful. It&#x27;s better to use this one, which is a real CLI tool: <a href="https:&#x2F;&#x2F;github.com&#x2F;vlisivka&#x2F;bash-modules&#x2F;blob&#x2F;master&#x2F;bash-modules&#x2F;examples&#x2F;showcase-arguments.sh" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;vlisivka&#x2F;bash-modules&#x2F;blob&#x2F;master&#x2F;bash-mo...</a>
评论 #33356292 未加载
rrwoover 2 years ago
One thing I try to do is retrieve information from the system instead of hardcoding it.<p>For example, instead of<p><pre><code> USER=mail UID=8 </code></pre> use<p><pre><code> USER=mail UID=$(id -u $USER) </code></pre> It improves portability and removes potential sources of errors.<p>Also note that this is something that should be done in any programming language, not just shell scripts.
remorsesover 2 years ago
The best practice for me is to not use bash or zsh, use a better defined and robust language like JavaScript or python
ww520over 2 years ago
These are really good information for shell script. I feel that not enough emphasis have been put on shell script development in general. Shell script is the glue language for lots of things. The power of a shell script is the all tools that it can call and orchestrate the data passing between the tools.
tpoacherover 2 years ago
I agree with most points except [[ ]] instead of test.<p>The explanation for that wasnt really an explanation either ...
davearmsover 2 years ago
Thank you for this. I have dropped a backlink for learners to find the article on exams.wiki&#x2F;bash-linkedin&#x2F;, and for myself to learn. I have also just started &quot;Command Line Fundamentals&quot; (Packt Publishing) to work through the theory and examples.
corytheboydover 2 years ago
The shellcheck plugin in JetBrains IDEs leveled up my bash scripting immediately. 100% recommend.
tuyiownover 2 years ago
More than one decade of shell script: bash is not shell, and talking about bash without version is suspicious.<p>I won&#x27;t check with for version those tips applies, and continue writing POSIX shell as much as can. I might check which or those suggestions are POSIX, though.
评论 #33356485 未加载
synergy20over 2 years ago
<p><pre><code> 1. use shellcheck 2. use shfmt (to format your shell script) 3. set -euo pipefail (much shorter) </code></pre> my slight complain about bash is that it disallows space around =, X=100 is OK, X = 100 is not, sometimes I just make mistakes like that.
bfungover 2 years ago
Also agree with basically all of it.<p>My order preference would be:<p><pre><code> 1. use shellcheck. … rest …</code></pre>
baxuzover 2 years ago
I switched to <a href="https:&#x2F;&#x2F;github.com&#x2F;google&#x2F;zx" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;google&#x2F;zx</a>. I&#x27;m tired of working with strings and prefer actual data structures.
nousermaneover 2 years ago
About that &quot;#!&#x2F;usr&#x2F;bin&#x2F;env bash&quot; business - are there any systems out there that have &quot;&#x2F;usr&#x2F;bin&#x2F;env&quot;, but do <i>not</i> have &quot;&#x2F;bin&#x2F;bash&quot;?
评论 #33355879 未加载
评论 #33356096 未加载
nickjjover 2 years ago
For local variables I&#x27;d also use the -r flag to explicitly mark read-only variables when possible. It makes it easier to glance at the code and know that variable isn&#x27;t expected to change.
ilytover 2 years ago
I&#x27;ll throw another one: If it is longer than a ~screen, throw it away and write it in &lt;scripting language present&gt; bash is just not a good language at the best of days
grapplerover 2 years ago
There is an actual, honest-to-goodness, standardized, current, Shell Command Language now. It&#x27;s part of POSIX.1-2017 or, if you like, IEEE Std 1003.1-2017.<p>Perhaps not surprisingly, it&#x27;s bourne shell, not bash. But still, it&#x27;s an actual published standard all can refer to when the language in question is &quot;shell scripts&quot;, i.e. .sh files, or &quot;shell commands&quot; in some context where a shell command is called for (e.g. portable makefiles).<p><pre><code> https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;utilities&#x2F;V3_chap02.html</code></pre>
ssratover 2 years ago
Please, please, please:<p>* Write help text to stdout, not stderr, so I can grep it<p>* Set exit status to 0 on success and 1 or some other small positive integer on failure so I can use || and &amp;&amp;
Emigre_over 2 years ago
These could be linting rules for bash script files.
评论 #33354657 未加载
Wowfunhappyover 2 years ago
What is the difference between `set -o errexit` (as recommended in the article) and `set -e` (which is the method I knew previously)?
zehhaxoxoover 2 years ago
Regarding<p>&gt; 9. Always quote variable accesses with double-quotes.<p>Does the author refer to &quot;$MYVAR&quot;? Why would you want to use that over ${MYVAR}?
ahungryover 2 years ago
Wrap the entire script in {}, otherwise a change to it will impact running instances (best case, causing an abrupt error).
bradwoodover 2 years ago
HEREDOC for help is nicer than echo IMHO
评论 #33355264 未加载
rrwoover 2 years ago
I try to use the long-form of command-line switches in scripts, e.g. `cp --force` instead of `cp -f`.
评论 #33355178 未加载
评论 #33355173 未加载
germandiagoover 2 years ago
I do all of this all the time.<p>But I use, set -euo pipefail. I think -u is -o unset ,etc? Just easier to type.
rrootover 2 years ago
1. If you have to start with a template, then shell script is not the right thing for whatever you&#x27;re trying to accomplish.<p>2. Shell scripts are wonderful, but once they exceed a few lines (give or take 50), they&#x27;ve entered the fast track on becoming a maintenance headache and a liability.
Arch-TKover 2 years ago
Naming your executable shell scripts with .sh has similar problems to Hungarian notation. If your ~&#x2F;.local&#x2F;bin shell script ends up useful in a lot of places, you may want to re-write it in something less crap (and I say that as an experienced bash abuser who knows it quite well and uses it a lot more than he should) than bash. When you do that, your python&#x2F;nim&#x2F;lua&#x2F;whatever script now has .sh at the end. What was the point?<p>.sh is appropriate for a shell library module which you source from another shell script. It is not really appropriate for something which is more abstract (such as a &quot;program&quot; inside your PATH).<p>set -e &#x2F; set -o errexit will only be helpful if you fundamentally understand exactly what it does, if you don&#x27;t, you are bound to end up with broken code. Once you fundamentally understand set -e you will be better placed to decide whether it is appropriate to use it or more appropriate to simply do proper error handling. The oft repeated mantra of using set -e is really misleading a lot of people into thinking that bash has some sane mode of operation which will reduce their chance of making mistakes, people should never be mislead to think that bash will ever do anything sane.<p>set -u &#x2F; set -o nounset breaks a lot of perfectly sensible bash idioms and is generally bad at what proponents of it claim it will help solve (using unset variables by accident or by misspelling). There are better linters which solve this problem much better without having to sacrifice some of what makes bash scripts easier to write&#x2F;read.<p>set -o pipefail is not an improvement&#x2F;detriment, it is simply changing the way that one of bash&#x27;s features functions. pipefail should only be set around specific uses of pipelines when it is known that it will produce the intended result. For example, take this common idiom:<p><pre><code> if foo | grep -q bar; then ... </code></pre> The above will NOT behave correctly (i.e. evaluate to a non-zero exit code) if grep -q closes its input as soon as it finds a match and foo handles the resulting SIGPIPE by exiting with a non-zero status code.<p>Guarding set -x &#x2F; set -o xtrace seems unnecessary, -x is already automatically inherited. Just set it before running the program.<p>Good advice on using [[ but it is important to fundamentally understand the nuances of this, quoting rules change within the context of [[.<p>Accepting h and help seems incredibly unnecessary. If someone who has never used a unix-like operating system happens upon your script then they may find it useful. But I don&#x27;t think catering to such a low common denominator makes sense. Your script should just handle invalid arguments by printing a usage statement with maybe a hint of how to get a full help message.<p>I&#x27;d say changing to your script&#x27;s directory is almost never appropriate.<p>Shellcheck, while useful, is useful only if you understand bash well.<p>The lesson here is that if you think that you have spent enough time writing bash to suggest best practices, you&#x27;ve not spent enough time writing bash. Only when you realise that the best practice is to not use bash have you used bash long enough (or short enough).<p>If you want to write a script which you&#x27;re going to rely on or distribute, learn bash inside out and then carefully consider if it&#x27;s still the right option.<p>If you are unwilling or unable to learn bash inside out then please use something else.<p>Do not be fooled into thinking that some &quot;best practices&quot; you read online will save you from bash.
评论 #33360392 未加载
oarsover 2 years ago
Do you guys think that Shell scripting will still be around in 20 years?
评论 #33355423 未加载
评论 #33358423 未加载
评论 #33356182 未加载
评论 #33355375 未加载
screwgothover 2 years ago
Some good ones in here. Especially the ones to &quot;set&quot; stuff.
nxpnsvover 2 years ago
I’ve scripted way longer than a decade. Stil, this is a great list!
kurtreedover 2 years ago
My shell script best practice is not to use shell script.
dlahodaover 2 years ago
awesome. this article and comments will make scripts tons better. is there resonable subset of zsh and bash? is there linter to enforce these?
uptherootsover 2 years ago
I didn&#x27;t know many of these! Thanks
gigatexalover 2 years ago
bash is rather ubiquitous but wouldn&#x27;t it make more sense to target &#x2F;bin&#x2F;sh?
consultSKIover 2 years ago
after 30+ years writing scripts, I picked up several cool ideas. #thx
rashthedudeover 2 years ago
Timing couldn&#x27;t be any better. Been getting serious about bash&#x2F;zsh scripting lately.
sylwareover 2 years ago
my experience: no bashism, indepotence, explicit error handling.
AYBABTMEover 2 years ago
Also: use functions.
pkruminsover 2 years ago
This guy shells!
评论 #33366955 未加载
hardlianotionover 2 years ago
&quot;Use bash&quot;<p>Are you listening Apple?
评论 #33363705 未加载
casey2over 2 years ago
More opinions<p>1. Bash shouldn&#x27;t be used, not because of portability, but because its features aren&#x27;t worth their weight and can be picked up by another command, I recommend (dash) any POSIX complaint shell (bash --posix included) so you aren&#x27;t tempted to use features of bash and zsh that are pointless, tricky or are there for interactivity. Current POSIX does quite well for what you would use shell for.<p>2. Never use #!&#x2F;usr&#x2F;bin&#x2F;env bash. Even if you are using full bash, bash should be installed in &#x2F;usr&#x2F;bin&#x2F;bash. If you don&#x27;t even know something this basic about the environment, then you shouldn&#x27;t be programming it, the script is likely to create a mess somewhere in the already strange environment of the system.<p>3. Don&#x27;t use extensions unless you&#x27;re writing for Windows machines. Do you add extensions to any other executable? head, sed can help you retrieve the first line of a file and neither of them have extensions.<p>4, 5, 6. You may do this is obscure scenarios where you absolutely cannot have a script run if there is any unforeseen error, but it&#x27;s definitely not something that should be put on without careful consideration, <a href="http:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;BashPitfalls#set_-euo_pipefail" rel="nofollow">http:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;BashPitfalls#set_-euo_pipefail</a> explains this better. And it goes without saying that this is not a substitute for proper error handling.<p>7. I agree that people should trace their shell scripts, but this has nothing to with shell.<p>8. [[]] is powerful, so I very often see it used when the [] builtin would suffice. Also, [[ is a command like done, not a bash builtin.<p>9. Quote only what needs quoting. If you don&#x27;t know what needs quoting, then you don&#x27;t understand your script. I know it seems like a waste of time, but it will make you a much better shell programmer then these always do&#x2F;don&#x27;t do X unless Y then do Z, rules that we are spouting.<p>10. Use either local or global variables in functions, depending on which you want. I see no reason to jump through this weird hoop because it might become an easily fixable problem later.<p>11. This is a feature, make usage appear when you blink, I don&#x27;t care, if anything variations of -h too limited,<p>12. Finally, one &quot;opinion&quot; we agree on, not sure how else to redirect to stderr, but I&#x27;m sure that other way isn&#x27;t as good as this one.<p>13. No, read the usage. If you want inferior long options, then you can add them to your scripts, but they are not self documenting, they only serve to make commands less readable and clutter completion.<p>14. No, it&#x27;s not usually appropriate, do you want all installed scripts writing to &#x2F;bin? The directory the script is running in should be clearly communicated to the user, with cd &quot;$(dirname &quot;$0&quot;)&quot;, &quot;It runs in the directory the script is in.&quot; Needs to be communicated somewhere, or you have failed.<p>15. Yes, use ShellCheck.<p>16. Please call your list Bash Script Practices if it&#x27;s unrelated to shell.
评论 #33356482 未加载
评论 #33356972 未加载
评论 #33358484 未加载
评论 #33356260 未加载
rnknover 2 years ago
&gt; 1. Use bash.<p>Credibility gone.
corser45over 2 years ago
&gt; Use bash. Yeaah, <i>closes tab</i>.
评论 #33356278 未加载