{"id":22808118,"url":"https://github.com/sixarm/unix-shell-script-tactics","last_synced_at":"2025-04-09T06:11:54.124Z","repository":{"id":61950900,"uuid":"49747220","full_name":"SixArm/unix-shell-script-tactics","owner":"SixArm","description":"Unix shell script tactics - best practices style guide","archived":false,"fork":false,"pushed_at":"2024-09-17T13:11:00.000Z","size":403,"stargazers_count":344,"open_issues_count":0,"forks_count":18,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-04-02T02:12:08.367Z","etag":null,"topics":["shell","style-guide","unix"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SixArm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-01-15T21:56:50.000Z","updated_at":"2025-02-19T19:57:27.000Z","dependencies_parsed_at":"2024-01-17T17:55:15.018Z","dependency_job_id":"f9c354bd-3b11-483b-b7c5-1ee045246e91","html_url":"https://github.com/SixArm/unix-shell-script-tactics","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/SixArm%2Funix-shell-script-tactics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SixArm%2Funix-shell-script-tactics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SixArm%2Funix-shell-script-tactics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SixArm%2Funix-shell-script-tactics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SixArm","download_url":"https://codeload.github.com/SixArm/unix-shell-script-tactics/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247987285,"owners_count":21028895,"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":["shell","style-guide","unix"],"created_at":"2024-12-12T11:08:00.953Z","updated_at":"2025-04-09T06:11:54.098Z","avatar_url":"https://github.com/SixArm.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Unix shell script tactics - best practices style guide\n\nThis Unix shell script style guide helps us write better Unix shell script code for speed, security, stability, and portability.\n\nThis guide is by SixArm.com, a software consultancy. Our customers use shell scripts within a wide variety of Unix shells, so we aim for POSIX for simple scripts.\n\nHighlights:\n\n  * [Aim for POSIX when possible because of portability and standardization](doc/aim-for-posix/)\n  * [Protect scripts by using `set` flags such as `set -euf`](doc/protect-scripts-by-using-set-flags/)\n  * [Print output with `printf` not `echo`](doc/print-output-with-printf-not-echo/)\n  * [Trap signals and exit by using `trap trap_exit EXIT`](doc/trap-signals-and-exit/)\n  * [Use a `main()` function](doc/use-a-main-function/)\n  * [Run executable with no file name extension](doc/run-executable-with-no-file-name-extension/)\n  * [Source with dot operator `.` not keyword `source`](doc/source-with-dot-operator-not-keyword-source/)\n  * [Version name: use semantic versioning](doc/version-name-use-semantic-versioning/)\n  * [Help: use a function and HERE document](doc/help-use-a-function-and-here-document/)\n  * [Date \u0026amp; time format: use UTC and ISO8601](doc/date-time-format-use-utc-and-iso8601/)\n  * [Booleans: use true and false](doc/booleans-use-true-and-false/)\n  * [Colors: use terminal escape codes \u0026 NO_COLOR \u0026 TERM=dumb](doc/colors-use-terminal-escape-codes-and-no-color-and-term-dumb/)\n  * [Subshells: use parentheses `$()` not backticks](doc/subshells-use-parentheses-not-backticks/)\n  * [Trace using set -x then set +x without printing](doc/trace-using-set-x-then-set-x-without-printing/)\n  * [Hunt for bugs by using ShellCheck](https://www.shellcheck.net/)\n  * [Fix some bugs automatically, if you want, by using Shellharden](https://github.com/anordal/shellharden/)\n\nRecommendations (details of these are TODO):\n\n  * Quote liberally such as `\"$var\"` instead of just `$var`, for safety.\n  * Bulletproof scripts to handle characters such as a quote, newline, leading dash.\n  * Enable a user to customize commands by using env vars such as `${FOO:-foo}`.\n  * Create temporary files by using `mktemp` instead of `tempfile` et. al.\n  \nDemo:\n\n  * [Unix shell script tactics demo](bin/unix-shell-script-tactics-demo/)\n\n\n## Topics\n\nArgument parsing:\n\n  * [for arg do loop](doc/for-arg-do-loop/)\n  * [Arg parse](doc/arg-parse/)\n  * [Parse options via `while` and `case` not `getopts` or `getopt`](doc/parse-options-via-while-and-case-not-getopts-or-getopt/)\n\nEnvironment variables:\n\n  * [Test if set or unset](doc/environment-variables/test-if-set-or-unset/)\n  * [$FUNCNAME function name](doc/environment-variables/funcname-function-name/)\n\nDirectories:\n\n  * [Script directory: use realpath or cd](doc/directories/script-directory-use-realpath-or-cd/)\n  * [Log directory: use $LOG_HOME](doc/directories/cache-directory-use-log-home/)\n  * [Data directory: use $XDG_DATA_HOME](doc/directories/data-directory-use-xdg-data-home/)\n  * [Cache directory: use $XDG_CACHE_HOME](doc/directories/cache-directory-use-xdg-cache-home/)\n  * [Configuration directory: use $XDG_CONFIG_HOME](doc/directories/configuration-directory-use-xdg-config-home/)\n  * [Runtime directory: use $XDG_RUNTIME_HOME](doc/directories/runtime-directory-use-xdg-runtime-home/)\n  * [Temporary directory:: use `mktemp`](doc/directories/temporary-directory-use-mktemp/)\n\nFiles:\n\n  * [Temporary file using `mktemp` and `trap`](doc/temporary-file-using-mktemp-and-trap/)\n  * [Find files with filter for permission denied](doc/find-files-with-filter-for-permission-denied/)\n  * [Find files with special characters](doc/find-files-with-special-characters/)\n  * [Find files with readable permissions](doc/find-files-with-readable-permissions/)\n  * [Find files with executable, perm, test, exec](doc/find-files-with-executable-perm-test-exec/)\n\nReferences:\n\n  * [Writing safe shell scripts](https://sipb.mit.edu/doc/safe-shell/)\n  * [Rich’s sh (POSIX shell) tricks](http://www.etalabs.net/sh_tricks.html/)\n  * [Google Shell Script Style Guide](https://google.github.io/styleguide/shell.xml/)\n  * [Filenames and Pathnames in Shell: How to do it Correctly](http://www.dwheeler.com/essays/filenames-in-shell.html/)\n  * [Standard Command-Line Options](http://www.tldp.org/LDP/abs/html/standard-options.html/)\n  * [How to do things safely in bash](https://github.com/anordal/shellharden/blob/master/how_to_do_things_safely_in_bash.md/)\n  * [pure sh bible](https://github.com/dylanaraps/pure-sh-bible) \u0026 [pure bash bible](https://github.com/dylanaraps/pure-bash-bible/)\n\nConventions:\n\n  * [Program name using a string or basename](doc/program-name-using-a-string-or-basename/)\n  * [Git top level directory using rev-parse](doc/git-top-level-directory-using-rev-parse/)\n  * [Functions: out, err, die, big, log, now, sec, zid, cmd, etc.](doc/functions-out-err-die-big-log-now-sec-zid-cmd-etc/)\n  * [Assert functions: assert_empty, assert_equal, assert_match](doc/assert-functions/)\n  * [sec() function portability](doc/sec-function-portability/)\n\nControl flow statements:\n\n  * [While loop with index counter](doc/while-loop-with-index-counter/)\n  * [Do while loop](doc/do-while-loop/)\n  * [Case statement that skips option dash flags](doc/case-statement-that-skips-option-dash-flags/)\n\nFunctions:\n\n  * [Export function](doc/export-function/)\n  * [Number functions](doc/number-functions/)\n  * [Array functions](doc/array-functions/)\n  * [URL encode](doc/url-encode/)\n  * [URL decode](doc/url-decode/)\n\nCommand snippets:\n\n  * [awk match_between](doc/awk-match-between/)\n\nCompatibilities:\n\n  * [`readlink` on macOS behaves differently](doc/readlink-on-macos-behaves-differently/)\n  * [`realpath` is` not available on older macOS default](doc/realpath-is-not-available-on-older-macos-default/)\n\nPostgreSQL psql:\n\n  * [psql helpers](doc/psql-helpers/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsixarm%2Funix-shell-script-tactics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsixarm%2Funix-shell-script-tactics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsixarm%2Funix-shell-script-tactics/lists"}