{"id":18876297,"url":"https://github.com/mbarany/bash-style-guide","last_synced_at":"2026-02-18T11:30:17.612Z","repository":{"id":150042623,"uuid":"130982382","full_name":"mbarany/bash-style-guide","owner":"mbarany","description":"Bash Style Guide","archived":false,"fork":false,"pushed_at":"2018-04-27T02:56:25.000Z","size":3,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-31T02:13:17.218Z","etag":null,"topics":["bash"],"latest_commit_sha":null,"homepage":null,"language":null,"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/mbarany.png","metadata":{"files":{"readme":"README.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}},"created_at":"2018-04-25T09:24:29.000Z","updated_at":"2019-08-22T00:56:39.000Z","dependencies_parsed_at":null,"dependency_job_id":"468c17e4-9949-4cc5-a9ee-ed45763e47e6","html_url":"https://github.com/mbarany/bash-style-guide","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbarany%2Fbash-style-guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbarany%2Fbash-style-guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbarany%2Fbash-style-guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbarany%2Fbash-style-guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mbarany","download_url":"https://codeload.github.com/mbarany/bash-style-guide/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239832432,"owners_count":19704607,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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"],"created_at":"2024-11-08T06:12:22.358Z","updated_at":"2026-02-18T11:30:17.549Z","avatar_url":"https://github.com/mbarany.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# bash-style-guide\nMy personal style guide for Bash.\n\n## When to use Shell\nShell should only be used for small utilities or simple wrapper scripts. While shell scripting isn't a development language, it is used for writing various utility scripts.\nSome guidelines:\n- If you are mostly calling other utilities and are doing relatively little data manipulation, shell is an acceptable choice for the task.\n- If performance matters, use something other than shell.\n- If you find you need to use arrays for anything more than assignment of ${PIPESTATUS}, you should **NOT** use shell.\n- If you are writing a script that is more than 100 lines long, you should probably **NOT** be writing it in shell. Bear in mind that scripts grow. Rewrite your script in another language early to avoid a time-consuming rewrite at a later date.\n\n## Syntax\n- Shebang\n  - Use POSIX compatible shebang.\n    ```bash\n    # Bad\n    #!/bin/bash\n\n    # Good\n    #!/usr/bin/env bash\n    ```\n  - Depend on bash (`#!/usr/bin/env bash`). Don't be afraid to use bash features like arrays. Using `#!/bin/sh` for maximum portability is commendable, but in reality most users have bash.\n- Use spaces instead of tabs. Preferably 2 spaces, but be consistent.\n- Use LF Unix-style line endings. AKA `\\n`.\n- Use `$(command)` instead of backticks.\n- Don't use `;` to separate statements and expressions. As a corollary - use one expression per line.\n- Always use curly braces for variable expansion so that there's no guessing the variable name.\n  ```bash\n  # Bad\n  echo $my_var\n  echo \"$my_foo\"\n  echo \"using file: my_$a_var_file\"\n\n  # Good\n  echo \"${my_var}\"\n  echo \"using file: my_${a_var}_file\"\n  ```\n\n## Environment Settings\n- Script settings\n  - Use `set -o errexit` (a.k.a. `set -e`) to make your script exit when a command fails. Then add `|| true` to commands that you allow to fail.\n  - Use `set -o nounset` (a.k.a. `set -u`) to exit when your script tries to use undeclared variables.\n  - Use `set -o pipefail` in scripts to catch `mysqldump` fails in e.g. `mysqldump | gzip`. The exit status of the last command that threw a non-zero exit code is returned.\n  - Use `set -o xtrace` (a.k.a `set -x`) to trace what gets executed. Useful for debugging.\n- Normal output should go to **STDOUT** and any errors should go to **STDERR**.\n\n## Naming\n- Functions: Lower-case, with underscores to separate words. Separate libraries with ::. Parentheses are required after the function name. The keyword function is optional, but must be used consistently throughout a project. Braces must be on the same line as the function name and no space between the function name and the parenthesis.\n  ```bash\n  # Single function\n  my_func() {\n    ...\n  }\n\n  # Part of a package\n  mypackage::my_func() {\n    ...\n  }\n  ```\n- Variables\n  - Same as functions\n  - Constants and environment variables should be all caps, separated with underscores, declared at the top of the file.\n    ```bash\n    # Constant\n    readonly PATH_TO_FILES='/some/path'\n\n    # Both constant and environment\n    declare -xr ORACLE_SID='PROD'\n    ```\n- Filenames should be lowercase, with hyphens to separate words if desired.\n- File Extensions\n  - Executables should have no extension (strongly preferred) or a .sh extension. Libraries must have a .sh extension and should not be executable.\n  - It is not necessary to know what language a program is written in when executing it and shell doesn't require an extension so we prefer not to use one for executables. However, for libraries it's important to know what language it is and sometimes there's a need to have similar libraries in different languages. This allows library files with identical purposes but different languages to be identically named except for the language-specific suffix.\n\n## Comments\n- Avoid superfluous comments. Prefer descriptive variable names.\n- Use one space between the leading `#` character of the comment and the text of the comment.\n\n## Conditionals\n- Use double brackets ([[ ]]) where possible over single brackets.\n\n## Best Practices\n- Variables\n  - Use `readonly` or `declare -r` to ensure they're read only.\n  - Declare function-specific variables with `local`. This avoids polluting the global name space and inadvertently setting variables that may have significance outside the function.\n- Functions\n  - Put all functions together at the top of the file just below constants. Don't hide executable code between functions.\n  - Never nest functions.\n- `main` function\n  - In order to easily find the start of the program, put the `main` program in a function called `main` as the bottom most function. This provides consistency with the rest of the code base as well as allowing you to define more variables as `local`. The last non-comment line in the file should be a call to `main`: `main \"$@\"`. Obviously, for short scripts where it's just a linear flow, `main` is overkill and so is not required.\n- `eval` should be avoided\n- Use a sensible line length. Preferably 80 characters, but no longer than 120.\n- If you're writing a script that basically forwards all of its arguments to another one, then use `exec` to avoid spawning a subshell. For example, in some systems `egrep` is just a wrapper script for `grep` that looks like this:\n  ```bash\n  #!/bin/sh\n\n  exec grep -E \"$@\"\n  ```\n\n## Conclusion\n- Use common sense and most importantly **BE CONSISTENT**.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmbarany%2Fbash-style-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmbarany%2Fbash-style-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmbarany%2Fbash-style-guide/lists"}