{"id":13495034,"url":"https://github.com/bahamas10/bash-style-guide","last_synced_at":"2026-01-27T01:32:00.973Z","repository":{"id":20091137,"uuid":"23360415","full_name":"bahamas10/bash-style-guide","owner":"bahamas10","description":"A style guide for writing safe, predictable, and portable bash scripts (not sh!)","archived":false,"fork":false,"pushed_at":"2025-12-05T04:05:41.000Z","size":45,"stargazers_count":918,"open_issues_count":1,"forks_count":96,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-12-08T05:55:28.722Z","etag":null,"topics":["bash-scripting","style-guide","ysap"],"latest_commit_sha":null,"homepage":"https://style.ysap.sh","language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bahamas10.png","metadata":{"files":{"readme":"README-cn.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2014-08-26T17:25:47.000Z","updated_at":"2025-12-05T22:54:04.000Z","dependencies_parsed_at":"2025-06-08T04:27:07.742Z","dependency_job_id":"3cb17f0d-7ef1-4597-ba06-053b4cc0a7dd","html_url":"https://github.com/bahamas10/bash-style-guide","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bahamas10/bash-style-guide","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahamas10%2Fbash-style-guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahamas10%2Fbash-style-guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahamas10%2Fbash-style-guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahamas10%2Fbash-style-guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bahamas10","download_url":"https://codeload.github.com/bahamas10/bash-style-guide/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahamas10%2Fbash-style-guide/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28795468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T01:07:07.743Z","status":"ssl_error","status_checked_at":"2026-01-27T01:07:06.974Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash-scripting","style-guide","ysap"],"created_at":"2024-07-31T19:01:30.571Z","updated_at":"2026-01-27T01:32:00.968Z","avatar_url":"https://github.com/bahamas10.png","language":"CSS","funding_links":[],"categories":["Others","CSS","Productivity tools"],"sub_categories":["Chess :chess_pawn:"],"readme":"Bash 风格指南\n================\n\n(note - this is now outdated - translations welcome)\n\n本风格指南旨在描述如何编写 bash 脚本，并使其安全和可预测。本指南基于 [this wiki](http://mywiki.wooledge.org)，特别是这个页面：\n\nhttp://mywiki.wooledge.org/BashGuide/Practices\n\n如本指南中有任何东西并未明确提出，则默认遵循这个 wiki 中所描述的观点。\n\n\n美学\n----------\n\n### 使用制表符还是空格\n\n制表符\n\n### 分号\n\n你无需在命令行中使用分号（我希望是这样），同样也不要在脚本中使用它。\n\n\n``` bash\n# wrong\nname='dave';\necho \"hello $name\";\n\n#right\nname='dave'\necho \"hello $name\"\n```\n\n### 函数\n\n不要使用关键字 `function` 创建函数。所有函数中创建的变量都应该声明为局部变量。\n\n``` bash\n# wrong\nfunction foo {\n    i=foo # this is now global, wrong\n}\n\n# right\nfoo() {\n    local i=foo # this is local, preferred\n}\n```\n\n### 代码块声明\n\n`then` 应与 `if` 放在同一行，`do` 应与 `while` 放在同一行。\n\n``` bash\n# wrong\nif true\nthen\n    ...\nfi\n\n# also wrong, though admittedly looks kinda cool\ntrue \u0026\u0026 {\n    ...\n}\n\n# right\nif true; then\n    ...\nfi\n```\n\n### 间距\n\n不要超过两个连续的换行符（即不超过一行空行）。\n\n\n### 注释\n\n注释没有明确的代码风格。除非你重写或者更新注释内容，否则不要因为美观的因素去改动它。\n\n\n\nBash 主义\n--------\n\n本风格指南用于 bash。这意味着，如果可以选择，使用 bash 的内建命令或关键字，总是好于外部命令或`sh(1)`的语法。\n\n \n### `test(1)`\n\n使用 `[[ ... ]]` 进行条件测试, 而不是 `[ .. ]` 或 `test ...`\n\n``` bash\n# wrong\ntest -d /etc\n\n# also wrong\n[ -d /etc ]\n\n# correct\n[[ -d /etc ]]\n```\n\n查看 http://mywiki.wooledge.org/BashFAQ/031 了解更多信息。\n\n### 队列\n\n使用 bash 的内部命令生成队列。\n\n``` bash\nn=10\n\n# wrong\nfor f in $(seq 1 5); do\n    ...\ndone\n\n# wrong\nfor f in $(seq 1 \"$n\"); do\n    ...\ndone\n\n# right\nfor f in {1..5}; do\n    ...\ndone\n\n# right\nfor ((i = 0; i \u003c n; i++)); do\n    ...\ndone\n```\n\n### 命令替换\n\n使用 `$(...)` 进行命令替换.\n\n``` bash\nfoo=`date`  # wrong\nfoo=$(date) # right\n```\n\n### 数学 / 整数操作\n\n使用 `((...))` 和 `$((...))`。\n\n``` bash\na=5\nb=4\n\n# wrong\nif [[ $a -gt $b ]]; then\n    ...\nfi\n\n# right\nif ((a \u003e b)); then\n    ...\nfi\n```\n\n**不要**使用 `let` 命令。\n\n### 参数扩展\n\n使用[参数扩展](http://mywiki.wooledge.org/BashGuide/Parameters#Parameter_Expansion)要好于使用外部命令，例如 `echo`, `sed`, `awk` 等等。\n\n\n``` bash\nname='bahamas10'\n\n# wrong\nprog=$(basename \"$0\")\nnonumbers=$(echo \"$name\" | sed -e 's/[0-9]//g')\n\n# right\nprog=${0##*/}\nnonumbers=${name//[0-9]/}\n```\n\n### 列出文件\n\n不要使用 [解析 ls(1)](http://mywiki.wooledge.org/ParsingLs)，而使用 bash 内置函数来循环文件。\n\n\n``` bash\n# very wrong, potentially unsafe\nfor f in $(ls); do\n    ...\ndone\n\n# right\nfor f in *; do\n    ...\ndone\n```\n\n### 查明可执行文件路径\n\n简单声明一点，你肯定不知道，如果你视图找出可执行程序的完整路径，你应该反思你的软件设计了。\n\n\n查看 http://mywiki.wooledge.org/BashFAQ/028 获取更多信息。\n\n### 数组和列表\n\n只要有可能，尽量使用 bash 数组来代替使用空格（或是换行符、制表符等）分隔的字符串。\n\n``` bash\n# wrong\nmodules='json httpserver jshint'\nfor module in $modules; do\n    npm install -g \"$module\"\ndone\n\n# right\nmodules=(json httpserver jshint)\nfor module in \"${modules[@]}\"; do\n    npm install -g \"$module\"\ndone\n```\n\n### 内置读取\n\n只要有可能，使用 bash 内置的 `read` 避免调用外部命令。\n\n例子：\n\n``` bash\nfqdn='computer1.daveeddy.com'\n\nIFS=. read hostname domain tld \u003c\u003c\u003c \"$fqdn\"\necho \"$hostname is in $domain.$tld\"\n# =\u003e \"computer1 is in daveeddy.com\"\n```\n\n外部命令\n-----------------\n\n### GNU 用户工具\n\n全世界不会都运行在 GNU 或 Linux 上；当调用外部命令时，例如 `awk`, `sed`, `grep`，避免 GNU 特定的选项，使其尽量易于移植。\n\n当你编写 bash ，并且使用给你的所有强大工具和 bash 的内建命令时，你会发现甚至很少有机会需要调用外部命令。\n\n\n### [UUOC](http://www.smallo.ruhr.de/award.html)\n\n不要在你不需要的时候使用 `cat(1)`。如果程序支持从标准输入读取，使用 bash 重定向传递数据。\n\n\n\n``` bash\n# wrong\ncat file | grep foo\n\n# right\ngrep foo \u003c file\n\n# also right\ngrep foo file\n```\n\n如果我们能够推断，当程序说它可以通过名称读取文件，并且这样做能获得更好的性能时，我们可以使用这个内置读取文件方法的命令行工具，而不是标准输入。\t\n\n\n风格\n-----\n\n### 引号\n\n当字符串需要变量扩展或命令替换插值的时候使用双引号，其它时候使用单引号。\n\n\n``` bash\n# right\nfoo='Hello World'\nbar=\"You are $USER\"\n\n# wrong\nfoo=\"hello world\"\n\n# possibly wrong, depending on intent\nbar='You are $USER'\n```\n\n所有将要经历分词的变量都 *必须* 被引用 (1)。如果分词不会发生，变量可以不加引号。\n\n\n``` bash\nfoo='hello world'\n\nif [[ -n $foo ]]; then   # 不需要引号 - [[ ... ]] 不会把变量分词\n    echo \"$foo\"          # 需要印号\nfi\n\nbar=$foo  # 不需要引号 - 变量不会分词\n```\n\n\n1. 唯一的例外是，如果代码或 bash 控制着这个变量的整个生命周期。这种情况 [basher](https://github.com/bahamas10/basher) 有类似的代码：\n\n``` bash\nprintf_date_supported=false\nif printf '%()T' \u0026\u003e/dev/null; then\n    printf_date_supported=true\nfi\n\nif $printf_date_supported; then\n    ...\nfi\n```\n\n在这个例子中，虽然在 `if` 声明中的 `$printf_date_supported` 将经历分词，但仍然不需要引号，因为这个变量的内容被明确地控制着，并不会从用户或其它命令里取值。\n\n同样的，例如 `$$`, `$?`, `$#`这些变量，也不需要引号，因为他们绝不会包含空格、制表符或换行符。\n\n然而，如果仍怀有疑问，可以查看[引用所有的扩展](http://mywiki.wooledge.org/Quotes)。\n\n### 变量声明\n\n避免大写的变量名，除非有一个很好的理由使用他们。不要使用 `let` 或 `readonly` 创建变量。`declare` 应该*只用于*关联数组。在函数中，应*始终*使用 `local` 声明变量。\n\n\n``` bash\n# wrong\ndeclare -i foo=5\nlet foo++\nreadonly bar='something'\nFOOBAR=baz\n\n# right\ni=5\n((i++))\nbar='something'\nfoobar=baz\n```\n\n### shebang\n\nBash 不总是位于 `/bin/bash`，因此尽量这样来写这一行：\n\n``` bash\n#!/usr/bin/env bash\n```\n\n### 错误检查\n\n举个例子，`cd` 不总是工作。请务必检查 `cd`（或类似的命令）任何可能的错误，如果错误存在就退出或将错误抛出。  \n\n\n``` bash\n# wrong\ncd /some/path # 可能会失败\nrm file       # 如果 cd 失败我在哪？我删除了什么？\n\n# right\ncd /some/path || exit\nrm file\n```\n\n### `set -e`\n\n不要设置 `errexit`。如同在 C 语言中，有时你想要得到一个错误，或是你期望什么执行失败，并不意味着你想要退出程序。\n\nhttp://mywiki.wooledge.org/BashFAQ/105\n\n\n\n### `eval`\n\n永远不要使用.\n\n---\n\n没有人会在代码库中接受下面这个链接列出的东西。\n\nhttp://mywiki.wooledge.org/BashPitfalls\n\n这里也例举了一些如何修复这些问题的例子。\n\nLicense\n-------\n\nMIT License\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahamas10%2Fbash-style-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbahamas10%2Fbash-style-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahamas10%2Fbash-style-guide/lists"}