bash Shell 脚本模板
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/430078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Shell script templates
提问by webwesen
What would be your suggestions for a good bash/ksh script template to use as a standard for all newly created scripts?
对于将一个好的 bash/ksh 脚本模板用作所有新创建脚本的标准,您有什么建议?
I usually start (after the #!
line) with a commented-out header with a filename, synopsis, usage, return values, author(s), changelog and would fit into 80-char lines.
我通常#!
以注释掉的标题开头(在该行之后),其中包含文件名、概要、用法、返回值、作者、更改日志,并且适合 80 个字符的行。
All documentation lines I start with double-hash symbols ##
so I can grep for them easily and local var names are prepended with "__".
所有文档行都以双散列符号开头,##
因此我可以轻松地为它们进行 grep,并且本地 var 名称以“__”开头。
Any other best practices? Tips? Naming conventions? What about return codes?
还有其他最佳实践吗?提示?命名约定?返回码呢?
Comments on version control : we use SVN all right, but another dept in the enterprise has a separate repo and this is their script. How do I know who to contact with Q's if there is no @author info? Using entries similar to javadocs has some merit even in the shell context, IMHO, but I might be wrong.
版本控制评论:我们用SVN没问题,但是企业的另一个部门有一个单独的repo,这是他们的脚本。如果没有@author 信息,我如何知道与 Q 联系的人?使用类似于 javadocs 的条目即使在 shell 上下文中也有一些优点,恕我直言,但我可能是错的。
采纳答案by Jonathan Leffler
I'd extend Norman's answer to 6 lines, and the last of those is blank:
我将诺曼的答案扩展到 6 行,最后一行是空白的:
#!/bin/ksh
#
# @(#)$Id$
#
# Purpose
?
The third line is a version control identification string - it is actually a hybrid with an SCCS marker '@(#)
' that can be identified by the (SCCS) program what
and an RCS version string which is expanded when the file is put under RCS, the default VCS I use for my private use. The RCS program ident
picks up the expanded form of $Id$
, which might look like $Id: mkscript.sh,v 2.3 2005/05/20 21:06:35 jleffler Exp $
. The fifth line reminds me that the script should have a description of its purpose at the top; I replace the word with an actual description of the script (which is why there's no colon after it, for example).
第三行是一个版本控制标识字符串 - 它实际上是一个混合体,带有一个 SCCS 标记 ' @(#)
',可以被 (SCCS) 程序识别,what
以及一个 RCS 版本字符串,当文件被放在 RCS 下时会被扩展,默认 VCS我用于我的私人用途。RCS 程序ident
采用 的扩展形式$Id$
,可能看起来像$Id: mkscript.sh,v 2.3 2005/05/20 21:06:35 jleffler Exp $
. 第五行提醒我,脚本应该在顶部有对其用途的描述;我用脚本的实际描述替换了这个词(例如,这就是为什么它后面没有冒号的原因)。
After that, there is essentially nothing standard for a shell script. There are standard fragments that appear, but no standard fragment that appears in every script. (My discussion assumes that scripts are written in Bourne, Korn, or POSIX (Bash) shell notations. There's a whole separate discussion on why anyone putting a C Shell derivative after the #!
sigil is living in sin.)
在那之后,shell 脚本基本上没有任何标准。出现了标准片段,但没有出现在每个脚本中的标准片段。(我的讨论假设脚本是用 Bourne、Korn 或 POSIX (Bash) shell 符号编写的。关于为什么有人在#!
sigil后面放置 C Shell 派生类的人生活在罪恶中,有一个完整的单独讨论。)
For example, this code appears in some shape or form whenever a script creates intermediate (temporary) files:
例如,每当脚本创建中间(临时)文件时,此代码就会以某种形状或形式出现:
tmp=${TMPDIR:-/tmp}/prog.$$
trap "rm -f $tmp.?; exit 1" 0 1 2 3 13 15
...real work that creates temp files $tmp.1, $tmp.2, ...
rm -f $tmp.?
trap 0
exit 0
The first line chooses a temporary directory, defaulting to /tmp if the user did not specify an alternative ($TMPDIR is very widely recognized and is standardized by POSIX). It then creates a file name prefix including the process ID. This is not a security measure; it is a simple concurrency measure, preventing multiple instances of the script from trampling on each other's data. (For security, use non-predictable file names in a non-public directory.) The second line ensures that the 'rm
' and 'exit
' commands are executed if the shell receives any of the signals SIGHUP (1), SIGINT (2), SIGQUIT (3), SIGPIPE (13) or SIGTERM (15). The 'rm
' command removes any intermediate files that match the template; the exit
command ensures that the status is non-zero, indicating some sort of error. The 'trap
' of 0 means that the code is also executed if the shell exits for any reason - it covers carelessness in the section marked 'real work'. The code at the end then removes any surviving temporary files, beforelifting the trap on exit, and finally exits with a zero (success) status. Clearly, if you want to exit with another status, you may - just make sure you set it in a variable before running the rm
and trap
lines, and then use exit $exitval
.
第一行选择一个临时目录,如果用户没有指定替代目录,则默认为 /tmp($TMPDIR 被广泛认可并由 POSIX 标准化)。然后它创建一个包含进程 ID 的文件名前缀。这不是一种安全措施;它是一种简单的并发措施,可防止脚本的多个实例相互践踏数据。(为了安全起见,在非公共目录。使用非预测的文件名)的第二行保证“ rm
”和“ exit
”如果外壳接收到任何信号SIGHUP(1)的命令被执行,SIGINT(2), SIGQUIT (3)、SIGPIPE (13) 或 SIGTERM (15)。' rm
' 命令删除任何与模板匹配的中间文件;该exit
命令确保状态非零,表示某种错误。这 'trap
' of 0 意味着如果 shell 出于任何原因退出,代码也会被执行 - 它涵盖了标记为“实际工作”的部分中的粗心大意。最后的代码然后删除所有幸存的临时文件,然后在退出时解除陷阱,最后以零(成功)状态退出。显然,如果您想以其他状态退出,您可以 - 只需确保在运行rm
和trap
行之前将其设置在变量中,然后使用exit $exitval
.
I usually use the following to remove the path and suffix from the script, so I can use $arg0
when reporting errors:
我一般用下面的来去掉脚本中的路径和后缀,这样就可以$arg0
在报错的时候使用:
arg0=$(basename error()
{
echo "$arg0: $*" 1>&2
exit 1
}
.sh)
I often use a shell function to report errors:
我经常使用一个shell函数来报错:
vflag=0
out=
file=
Dflag=
while getopts hvVf:o:D: flag
do
case "$flag" in
(h) help; exit 0;;
(V) echo "$arg0: version $Revision$ ($Date$)"; exit 0;;
(v) vflag=1;;
(f) file="$OPTARG";;
(o) out="$OPTARG";;
(D) Dflag="$Dflag $OPTARG";;
(*) usage;;
esac
done
shift $(expr $OPTIND - 1)
If there's only one or maybe two error exits, I don't bother with the function; if there are any more, I do because it simplifies the coding. I also create more or less elaborate functions called usage
to give the summary of how to use the command - again, only if there's more than one place where it would be used.
如果只有一个或两个错误退出,我不理会这个函数;如果还有更多,我会这样做,因为它简化了编码。我还创建了或多或少复杂的函数,usage
用于给出如何使用命令的摘要——同样,只有在不止一个地方使用命令时。
Another fairly standard fragment is an option parsing loop, using the getopts
shell built-in:
另一个相当标准的片段是一个选项解析循环,使用getopts
内置的shell:
shift $(($OPTIND - 1))
or:
或者:
: ${PERL:=perl}
: ${SED:=sed}
The quotes around "$OPTARG" handle spaces in arguments. The Dflag is cumulative, but the notation used here loses track of spaces in arguments. There are (non-standard) ways to work around that problem, too.
"$OPTARG" 周围的引号处理参数中的空格。Dflag 是累积的,但这里使用的符号丢失了参数中的空格。也有(非标准)方法可以解决该问题。
The first shift notation works with any shell (or would do if I used back-ticks instead of '$(...)
'. The second works in modern shells; there might even be an alternative with square brackets instead of parentheses, but this works so I've not bothered to work out what that is.
第一个移位表示法适用于任何外壳(或者如果我使用反引号而不是“ $(...)
”,则可以使用。第二个适用于现代外壳;甚至可能还有方括号而不是圆括号的替代方法,但这有效,所以我已经不费心去弄清楚那是什么。
One final trick for now is that I often have both the GNU and a non-GNU version of programs around, and I want to be able to choose which I use. Many of my scripts, therefore, use variables such as:
现在的最后一个技巧是,我经常同时拥有 GNU 和非 GNU 版本的程序,并且我希望能够选择我使用的那个。因此,我的许多脚本都使用变量,例如:
#!/bin/sh
## Usage: myscript [options] ARG1
##
## Options:
## -h, --help Display this message.
## -n Dry-run; only show what would be done.
##
usage() {
[ "$*" ] && echo "#!/bin/ksh
#================================================================
# HEADER
#================================================================
#% SYNOPSIS
#+ ${SCRIPT_NAME} [-hv] [-o[file]] args ...
#%
#% DESCRIPTION
#% This is a script template
#% to start any good shell script.
#%
#% OPTIONS
#% -o [file], --output=[file] Set log file (default=/dev/null)
#% use DEFAULT keyword to autoname file
#% The default value is /dev/null.
#% -t, --timelog Add timestamp to log ("+%y/%m/%d@%H:%M:%S")
#% -x, --ignorelock Ignore if lock file exists
#% -h, --help Print this help
#% -v, --version Print script information
#%
#% EXAMPLES
#% ${SCRIPT_NAME} -o DEFAULT arg1 arg2
#%
#================================================================
#- IMPLEMENTATION
#- version ${SCRIPT_NAME} (www.uxora.com) 0.0.4
#- author Michel VONGVILAY
#- copyright Copyright (c) http://www.uxora.com
#- license GNU General Public License
#- script_id 12345
#-
#================================================================
# HISTORY
# 2015/03/01 : mvongvilay : Script creation
# 2015/04/01 : mvongvilay : Add long options and improvements
#
#================================================================
# DEBUG OPTION
# set -n # Uncomment to check your syntax, without execution.
# set -x # Uncomment to debug this shell script
#
#================================================================
# END_OF_HEADER
#================================================================
: $*"
sed -n '/^##/,/^$/s/^## \{0,1\}//p' " #== needed variables ==#
SCRIPT_HEADSIZE=$(head -200 # Display help
$ ./template.sh --help
SYNOPSIS
template.sh [-hv] [-o[file]] args ...
DESCRIPTION
This is a script template
to start any good shell script.
OPTIONS
-o [file], --output=[file] Set log file (default=/dev/null)
use DEFAULT keyword to autoname file
The default value is /dev/null.
-t, --timelog Add timestamp to log ("+%y/%m/%d@%H:%M:%S")
-x, --ignorelock Ignore if lock file exists
-h, --help Print this help
-v, --version Print script information
EXAMPLES
template.sh -o DEFAULT arg1 arg2
IMPLEMENTATION
version template.sh (www.uxora.com) 0.0.4
author Michel VONGVILAY
copyright Copyright (c) http://www.uxora.com
license GNU General Public License
script_id 12345
# Display version info
$ ./template.sh -v
IMPLEMENTATION
version template.sh (www.uxora.com) 0.0.4
author Michel VONGVILAY
copyright Copyright (c) http://www.uxora.com
license GNU General Public License
script_id 12345
|grep -n "^# END_OF_HEADER" | cut -f1 -d:)
SCRIPT_NAME="$(basename set -o errexit
)"
#== usage functions ==#
usage() { printf "Usage: "; head -${SCRIPT_HEADSIZE:-99} set -o nounset
| grep -e "^#+" | sed -e "s/^#+[ ]*//g" -e "s/${SCRIPT_NAME}/${SCRIPT_NAME}/g" ; }
usagefull() { head -${SCRIPT_HEADSIZE:-99} set -o noclobber
| grep -e "^#[%+-]" | sed -e "s/^#[%+-]//g" -e "s/${SCRIPT_NAME}/${SCRIPT_NAME}/g" ; }
scriptinfo() { head -${SCRIPT_HEADSIZE:-99} set -o pipefail
| grep -e "^#-" | sed -e "s/^#-//g" -e "s/${SCRIPT_NAME}/${SCRIPT_NAME}/g"; }
"
exit 2
} 2>/dev/null
main() {
while [ $# -gt 0 ]; do
case in
(-n) DRY_RUN=1;;
(-h|--help) usage 2>&1;;
(--) shift; break;;
(-*) usage ": unknown option";;
(*) break;;
esac
done
: do stuff.
}
And then, when I need to invoke Perl or sed
, the script uses $PERL
or $SED
. This helps me when something behaves differently - I can choose the operational version - or while developing the script (I can add extra debug-only options to the command without modifying the script). (See Shell parameter expansionfor information on the ${VAR:=value}
and related notations.)
然后,当我需要调用 Perl or 时sed
,脚本使用$PERL
or $SED
。当某些行为不同时,这对我有帮助 - 我可以选择操作版本 - 或者在开发脚本时(我可以在不修改脚本的情况下向命令添加额外的仅调试选项)。(有关和相关符号的信息,请参阅Shell 参数扩展${VAR:=value}
。)
回答by Mark Edgar
I use the first set of ## lines for the usage documentation. I can't remember now where I first saw this.
我使用第一组## 行作为使用文档。我现在不记得我第一次看到这个的地方。
shopt -s nullglob
回答by Michel VONGVILAY uxora.com
This is the header I use for my script shell (bash or ksh).
It is a man
look alike and it is used to display usage() as well.
这是我用于脚本 shell(bash 或 ksh)的头文件。它man
看起来很像,也用于显示 usage()。
set -o errexit -o nounset -o noclobber -o pipefail
shopt -s nullglob
And here is the usage functions to go with:
这是要使用的使用函数:
# Script to turn lead into gold
# Copyright (C) 2009 Ima Hacker ([email protected])
# Permission to copy and modify is granted under the foo license
# Last revised 1/1/2009
Here is what you should obtain:
以下是您应该获得的:
# I am not crazy, this really is the only way to do this
You can get the full script template here: http://www.uxora.com/unix/shell-script/18-shell-script-template
您可以在此处获取完整的脚本模板:http: //www.uxora.com/unix/shell-script/18-shell-script-template
回答by l0b0
Enabling error detection makes it much easier to detect problems in the script early:
启用错误检测可以更轻松地及早检测脚本中的问题:
if [ $i = 1 ]; then
... some code
fi
Exit script on first error. That way you avoid continuing on to do something which depended on something earlier in the script, perhaps ending up with some weird system state.
第一个错误时退出脚本。这样你就可以避免继续做一些依赖于脚本早期内容的事情,也许最终会出现一些奇怪的系统状态。
[ $i = 1 ] && {
... some code
}
Treat references to unset variables as errors. Very important to avoid running things like rm -you_know_what "$var/"
with an unset $var
. If you know that the variable can be unset, and this is a safe situation, you can use ${var-value}
to use a different value if it's unset or ${var:-value}
to use a different value if it's unset orempty.
将对未设置变量的引用视为错误。避免rm -you_know_what "$var/"
使用 unset 之类的东西运行非常重要$var
。如果您知道该变量可以取消设置,这是一个安全的情况下,你可以使用${var-value}
使用不同的值,如果它没有设置或者${var:-value}
如果它未设置使用不同的值或空。
if [ $i -ne 1 ]; then
... some code
fi
It's easy to make the mistake of inserting a >
where you meant to insert <
, and overwrite some file which you meant to read. If you need to clobber a file in your script, you can disable this before the relevant line and enable it again afterwards.
很容易犯>
在您要插入的位置插入 的错误<
,并覆盖您要读取的某些文件。如果您需要破坏脚本中的文件,您可以在相关行之前禁用它并在之后再次启用它。
[ $i = 1 ] || {
... some code
}
Use the first non-zero exit code (if any) of a set of piped command as the exit code of the full set of commands. This makes it easier to debug piped commands.
使用一组管道命令的第一个非零退出代码(如果有)作为全套命令的退出代码。这使得调试管道命令变得更容易。
cat << EOF > foo.sh
printf "%s was here" "$name"
EOF
Avoid that your /foo/*
glob is interpreted literallyif there are no files matching that expression.
如果没有与该表达式匹配的文件,请避免按字面/foo/*
解释您的glob 。
You can combine all of these in two lines:
您可以将所有这些组合成两行:
printf "%s was here" "$name"
回答by Tim Post
Any code that is going to be released in the wild should have the following short header:
任何要在野外发布的代码都应该有以下简短的标题:
#!/bin/bash
## DESCRIPTION:
## AUTHOR: $USER_FULLNAME
declare -r SCRIPT_NAME=$(basename "$BASH_SOURCE" .sh)
## exit the shell(default status code: 1) after printing the message to stderr
bail() {
echo -ne "" >&2
exit ${2-1}
}
## help message
declare -r HELP_MSG="Usage: $SCRIPT_NAME [OPTION]... [ARG]...
-h display this help and exit
"
## print the usage and exit the shell(default status code: 2)
usage() {
declare status=2
if [[ "" =~ ^[0-9]+$ ]]; then
status=
shift
fi
bail "$HELP_MSG" $status
}
while getopts ":h" opt; do
case $opt in
h)
usage 0
;;
\?)
usage "Invalid option: -$OPTARG \n"
;;
esac
done
shift $(($OPTIND - 1))
[[ "$#" -lt 1 ]] && usage "Too few arguments\n"
#==========MAIN CODE BELOW==========
Keeping a change log going in code headers is a throwback from when version control systems were terribly inconvenient. A last modified date shows someone how old the script is.
当版本控制系统非常不方便时,在代码标头中保留更改日志是一种倒退。最后修改日期向某人显示脚本的年龄。
If you are going to be relying on bashisms, use #!/bin/bash , not /bin/sh, as sh is the POSIX invocation of any shell. Even if /bin/sh points to bash, many features will be turned off if you run it via /bin/sh. Most Linux distributions will not take scripts that rely on bashisms, try to be portable.
如果您要依赖 bashisms,请使用 #!/bin/bash 而不是 /bin/sh,因为 sh 是任何 shell 的 POSIX 调用。即使 /bin/sh 指向 bash,如果您通过 /bin/sh 运行它,许多功能也会被关闭。大多数 Linux 发行版不会采用依赖于 bashisms 的脚本,尽量做到可移植。
To me, comments in shell scripts are sort of silly unless they read something like:
对我来说,shell 脚本中的注释有点愚蠢,除非它们读到类似的内容:
#!/bin/ksh
Shell scripting is so simple that (unless you're writing a demonstration to teach someone how to do it) the code nearly always explains itself.
Shell 脚本编写非常简单(除非您正在编写演示来教某人如何操作)代码几乎总是能自我解释。
Some shells don't like to be fed typed 'local' variables. I believe to this day Busybox (a common rescue shell) is one of them. Make GLOBALS_OBVIOUS instead, it's much easier to read, especially when debugging via /bin/sh -x ./script.sh.
一些 shell 不喜欢输入类型化的“本地”变量。我相信直到今天 Busybox(一个常见的救援外壳)就是其中之一。改为使用 GLOBALS_OBVIOUS,它更容易阅读,尤其是在通过 /bin/sh -x ./script.sh 调试时。
My personal preference is to let logic speak for itself and minimize work for the parser. For instance, many people might write:
我个人的偏好是让逻辑不言自明,并尽量减少解析器的工作。例如,很多人可能会写:
#!/bin/bash
# [ID LINE]
##
## FILE: [Filename]
##
## DESCRIPTION: [Description]
##
## AUTHOR: [Author]
##
## DATE: [XX_XX_XXXX.XX_XX_XX]
##
## VERSION: [Version]
##
## USAGE: [Usage]
##
Where I'd just:
我只想:
#!/bin/bash -
#title :mkscript.sh
#description :This script will make a header for a bash script.
#author :your_name_here
#date :20110831
#version :0.3
#usage :bash mkscript.sh
#notes :Vim and Emacs are needed to use this script.
#bash_version :4.1.5(1)-release
#===============================================================================
Likewise, someone might write:
同样,有人可能会写:
##代码##... where I'd:
......我会:
##代码##The only time I use conventional if / then / else is if there's an else-if to throw in the mix.
我唯一一次使用传统的 if / then / else 是如果有一个 else-if 可以加入。
A horribly insane example of very good portable shell code can be studied by just viewing the 'configure' script in most free software packages that use autoconf. I say insane because its 6300 lines of code that caters to every system known to humankind that has a UNIX like shell. You don't want that kind of bloat, but it is interesting to study some of the various portability hacks within.. such as being nice to those who might point /bin/sh to zsh :)
可以通过查看大多数使用 autoconf 的免费软件包中的“配置”脚本来研究非常好的可移植 shell 代码的一个非常疯狂的例子。我说疯狂是因为它的 6300 行代码迎合了人类已知的每个具有类似 UNIX 的 shell 的系统。您不想要那种膨胀,但是研究其中的一些各种可移植性技巧很有趣..例如对那些可能将 /bin/sh 指向 zsh 的人表示友好:)
The only other advice I can give is watch your expansion in here-docs, i.e.
我能给出的唯一其他建议是在此处的文档中观看您的扩展,即
##代码##... is going to expand $name, when you probably want to leave the variable in place. Solve this via:
... 将扩展 $name,当您可能想要保留变量时。通过以下方式解决此问题:
##代码##which will leave $name as a variable, instead of expanding it.
这将使 $name 作为变量,而不是扩展它。
I also highly recommend learning how to use trap to catch signals .. and make use of those handlers as boilerplate code. Telling a running script to slow down with a simple SIGUSR1 is quite handy :)
我还强烈建议学习如何使用陷阱来捕捉信号……并将这些处理程序用作样板代码。用一个简单的 SIGUSR1 告诉正在运行的脚本放慢速度非常方便:)
Most new programs that I write (which are tool / command line oriented) start out as shell scripts, it's a great way to prototype UNIX tools.
我编写的大多数新程序(面向工具/命令行)都是从 shell 脚本开始的,这是 UNIX 工具原型的好方法。
You might also like the SHC shell script compiler, check it out here.
您可能还喜欢 SHC shell 脚本编译器,请在此处查看。
回答by Hui Zheng
My bash template is as below(set in my vim configuration):
我的 bash 模板如下(在我的vim 配置中设置):
##代码##回答by Norman Ramsey
I would suggest
我会建议
##代码##and that's it. Heavyweight block comments for shell scripts? I get the willies.
就是这样。shell 脚本的重量级块注释?我得到了威利。
Suggestions:
建议:
Documentation should be data or code, not comments. At least a
usage()
function. Have a look at how ksh and the other AST tools document themselves with --man options on every command. (Can't link because the web site is down.)Declare local variables with
typeset
. That's what it's for. No need for nasty underscores.
文档应该是数据或代码,而不是注释。至少有一个
usage()
功能。看看 ksh 和其他 AST 工具如何在每个命令上使用 --man 选项记录自己。(无法链接,因为网站已关闭。)用 声明局部变量
typeset
。这就是它的用途。不需要讨厌的下划线。
回答by J. M. Becker
Generally, I have a few conventions I like to stick to for every script I write. I write all scripts with assumption that other people might read them.
通常,对于我编写的每个脚本,我都有一些我喜欢遵守的约定。我编写所有脚本的前提是其他人可能会阅读它们。
I start every script with my header,
我用我的标题开始每个脚本,
##代码##I use that date format, for easier grep/searching. I use the '[' braces to indicate text people need to enter themselves. if they occur outside a comment, I try to start them with '#['. That way if someone pastes them as is, it wont be mistaken for input or a test command. Check the usage section on a man page, to see this style as an example.
我使用该日期格式,以便更轻松地进行 grep/搜索。我使用“[”大括号来表示人们需要自己输入的文本。如果它们出现在评论之外,我会尝试以“#[”开头。这样,如果有人按原样粘贴它们,就不会被误认为是输入或测试命令。检查手册页上的用法部分,以这种风格为例。
When I want to comment out a line of code, I use a single '#'. When I am doing a comment as a note, I use a double '##'. The /etc/nanorc
uses that convention also. I find it helpful, to differentiate a comment that was chosen not to execute; verses a comment that was created as a note.
当我想注释掉一行代码时,我使用单个“#”。当我将评论作为笔记进行评论时,我使用双 '##'。在 /etc/nanorc
使用该公约也。我发现区分被选择不执行的评论很有帮助;诗句作为笔记创建的评论。
All my shell variables, I prefer to do in CAPS. I try to keep between 4 - 8 characters, unless otherwise necessary. The names relate, as best as possible, with their usage.
我所有的 shell 变量,我更喜欢用大写字母来做。我尽量保持在 4 - 8 个字符之间,除非另有必要。这些名称尽可能与其用法相关。
I also always exit with 0 if successful, or a 1 for errors. If the script has many different types of errors (and would actually help someone, or could be used in some code in some way), I would choose a documented sequence over 1. In general, exit codes are not as strictly enforced in the *nix world. Unfortunately I have never found a good general number scheme.
如果成功,我也总是以 0 退出,否则以 1 退出。如果脚本有许多不同类型的错误(并且实际上可以帮助某人,或者可以以某种方式在某些代码中使用),我会选择超过 1 的记录序列。通常,退出代码在 * 中没有严格执行尼克斯世界。不幸的是,我从来没有找到一个好的通用数字方案。
I like to process arguments in the standard manner. I always prefer getopts, to getopt. I never do some hack with 'read' commands and if statements. I also like to use the case statement, to avoid nested ifs. I use a translating script for long options, so --help means -h to getopts. I write all scripts in either bash (if acceptable) or generic sh.
我喜欢以标准方式处理参数。我总是更喜欢 getopts,而不是 getopt。我从不使用“读取”命令和 if 语句进行一些破解。我也喜欢使用 case 语句,以避免嵌套 ifs。对于长选项,我使用翻译脚本,因此 --help 意味着 -h 到 getopts。我用 bash(如果可以接受)或通用 sh 编写所有脚本。
I NEVER use bash interpreted symbols (or any interpreted symbol) in filenames, or any name for that matter. specifically... " ' ` $ & * # () {} [] -, I use _ for spaces.
我从不在文件名或任何名称中使用 bash 解释符号(或任何解释符号)。特别是..." ' ` $ & * # () {} [] -,我使用 _ 表示空格。
Remember, these are just conventions. Best practice, of coarse, but sometimes you are forced outside the lines. The most important is to be consistent across and within your projects.
请记住,这些只是约定。最佳实践,粗略的,但有时你被迫在外线。最重要的是在您的项目之间和内部保持一致。
回答by userend
What you can do is to make a script that creates a header for a script & and have it auto open in your favorite editor. I saw a guy do that at this site:
您可以做的是制作一个脚本,为脚本创建一个标题 & 并让它在您最喜欢的编辑器中自动打开。我看到一个人在这个网站上这样做:
##代码##