{"id":49583868,"url":"https://github.com/ishbguy/baux","last_synced_at":"2026-05-03T21:37:17.915Z","repository":{"id":49364598,"uuid":"124678726","full_name":"ishbguy/baux","owner":"ishbguy","description":"BAUX is a bash auxiliary library for writing script.","archived":false,"fork":false,"pushed_at":"2019-03-19T14:56:42.000Z","size":145,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-05-03T21:37:16.815Z","etag":null,"topics":["assertion","bash","library","log","shell","test","testing","unit-test"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ishbguy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-10T17:16:32.000Z","updated_at":"2023-01-26T13:05:33.000Z","dependencies_parsed_at":"2022-09-25T05:23:35.359Z","dependency_job_id":null,"html_url":"https://github.com/ishbguy/baux","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ishbguy/baux","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ishbguy%2Fbaux","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ishbguy%2Fbaux/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ishbguy%2Fbaux/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ishbguy%2Fbaux/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ishbguy","download_url":"https://codeload.github.com/ishbguy/baux/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ishbguy%2Fbaux/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32586187,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"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":["assertion","bash","library","log","shell","test","testing","unit-test"],"created_at":"2026-05-03T21:37:17.155Z","updated_at":"2026-05-03T21:37:17.908Z","avatar_url":"https://github.com/ishbguy.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# [BAUX](https://github.com/ishbguy/baux)\n\n[![Travis][travissvg]][travis] [![Codecov][codecovsvg]][codecov] [![Codacy][codacysvg]][codacy] [![Version][versvg]][ver] [![License][licsvg]][lic]\n\n[travissvg]: https://travis-ci.org/ishbguy/baux.svg?branch=master\n[travis]: https://travis-ci.org/ishbguy/baux\n[codecovsvg]: https://codecov.io/gh/ishbguy/baux/branch/master/graph/badge.svg\n[codecov]: https://codecov.io/gh/ishbguy/baux\n[codacysvg]: https://api.codacy.com/project/badge/Grade/9a7820362a97474b87652d1519714e1b\n[codacy]: https://www.codacy.com/app/ishbguy/baux?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=ishbguy/baux\u0026amp;utm_campaign=Badge_Grade\n[versvg]: https://img.shields.io/badge/version-v0.0.1-lightgrey.svg\n[ver]: https://img.shields.io/badge/version-v0.1.0-lightgrey.svg\n[licsvg]: https://img.shields.io/badge/license-MIT-green.svg\n[lic]: https://github.com/ishbguy/baux/blob/master/LICENSE\n\n**BAUX** is a bash auxiliary library for writing script.\n\n## Table of Contents\n\n+ [:art: Features](#art-features)\n+ [:straight_ruler: Prerequisite](#straight_ruler-prerequisite)\n+ [:rocket: Installation](#rocket-installation)\n+ [:notebook: Usage](#notebook-usage)\n+ [:hibiscus: Contributing](#hibiscus-contributing)\n+ [:boy: Authors](#boy-authors)\n+ [:scroll: License](#scroll-license)\n\n## :art: Features\n\n+ [**Helper**](#helper-functions-bauxsh): Basic script writing helper functions, such as getting script's name, version and help message, importing other script once, warning or exit when get a wrong status. (`baux.sh`)\n+ [**Assertion**](#assertion-ensuresh): Functions for writing reliable APIs, ensuring the pre- or post-condition. (`ensure.sh`)\n+ [**Utility**](#utility-utilish): Useful utility functions for getting options, reading a simple config file, printing message with color and so on. (`utils.sh`)\n+ [**Debugging**](#debugging-logsh-tracesh): Simple functions for logging (`log.sh`) and print callstack when failed (`trace.sh`).\n+ [**Testing**](#testing-varsh-testsh): Functions for check a variable (`var.sh`) and writing unit tests (`test.sh`).\n+ [**Exception**](#exception-exceptsh): (Not yet finished)\n    - `try()`, `catch()`, `throw()`.\n+ [**Array**](#array-arraysh): Functions for array manipulation. (`array.sh`)\n    - Data structure: stack, queue.\n    - Sort and search: `sort()`, `bsearch()`.\n+ [**Pattern**](#pattern-patternsh): POSIX compatible characters patterns and other common regex. (`pattern.sh`)\n    - Pattern match: IP, URL, tele-number, etc.\n    - `is` pattern check.\n\n## :straight_ruler: Prerequisite\n\n\u003e + [`bash`](https://www.gnu.org/software/bash/bash.html)\n\u003e + [`sed`](https://www.gnu.org/software/sed/)\n\n## :rocket: Installation\n\nYou can get this program with `git`:\n\n```\n$ git clone https://github.com/ishbguy/baux\n```\n\n## :notebook: Usage\n\n### Library Hierarchy\n\n```bash\nlib\n├── array.sh    # array manipulate functions\n├── baux.sh     # basic helper functions\n├── pattern.sh  # POSIX compatible characters patterns and other common regex\n├── ensure.sh   # assertion functions\n├── except.sh   # not yet finished\n├── log.sh      # simple logging\n├── test.sh     # unit test functions\n├── trace.sh    # simple callstack function\n├── utils.sh    # useful tools\n└── var.sh      # checking variables\n```\n\n### Library Dependence Diagram\n\n```bash\nexcept.sh\n    |-----------------------------------------------+\n    V                                               |\narray.sh    test.sh                                 |\n    |           |-----------------------------------|\n    V           V                                   V\nvar.sh      utils.sh    pattern.sh    log.sh      trace.sh\n    |           |           |           |           |\n    +-----------+-----------+-----------+-----------+\n    V\nbaux.sh \u003c-\u003e ensure.sh\n```\n\n### How to Use BAUX Library?\n\nAs the [Library Dependence Diagram](#library-dependence-diagram) above, you can easily source one of the library file to include the functions you need, for example:\n\n```bash\n# in your script\nsource /path/to/baux/lib/baux.sh\n\n[[ -e $file ]] || die \"$file not exist.\"\n```\n\n### Helper Functions (`baux.sh`)\n\n#### Warning\n\n```bash\n# your script\nsource /path/to/baux/lib/baux.sh\n\n[[ -e $opt_file ]] || warn \"Just warn you that $opt_file does not exsit\"\n[[ -e $need_file ]] || die \"$need_file not found! This will exit with $BAUX_EXIT_CODE\"\n\necho \"Can not be here.\"\n```\n\n**PS**: Though `warn` runs successfully, it does `return ((++BAUX_EXIT_CODE))` in the end, so `warn` returns an **none-zero** when it finished!\n\n#### Information\n\n```bash\n#! /usr/bin/env bash\n# your script\nsource /path/to/baux/lib/baux.sh\n\necho \"The script name is $(proname)\" # will print the script name\n\nVERSION=\"v0.0.1\" # need to define VERSION first, or version will warn\necho \"The script version is $(version)\" # will print the script version\n\nHELP=\"This is a help message.\" # need to define HELP first, or usage will warn\nusage                          # print help message\n```\n\n**PS**: `usage` call `version` first to print version message, then print help message, so, both `VERSION` and `HELP` should be predefined when call `usage`.\n\n#### Importation\n\n`baux.sh` includes an `import` function to ensure source a file for only one time.\n\n```bash\nsource /path/to/baux/lib/baux.sh\n\nimport /path/to/your/lib.sh         # this will import once\nimport /path/to/your/lib.sh         # OK, but will not import lib.sh again\n\ncmd_from_lib_sh\n\nimport /file/not/exsit.sh           # this will fail, and make you script die\n\necho \"Can not be here!\"\n```\n\n### Assertion (`ensure.sh`)\n\nAssertion functions are useful for writing APIs, and they can be sorted in 3 catogories: general, explicit and implicit assertion.\n\n#### General Assertion\n\n`ensure` can make an assertion with a given expression, if the expression is true, it will continue to run the following commands, or it will die and print a given message.\n\n```bash\nsource /path/to/baux/lib/ensure.sh\n\n# the first arg is expression, the second arg is error message, which is optional\n\nNUM=1\nensure \"$NUM == 1\" \"$NUM must be equal 1\"       # OK\nensure \"2 -gt $NUM\" \"2 must greater than $NUM\"  # OK\n\nensure \"$NUM == 1.0\" \"$NUM must be 1.0\"         # this will die, for $NUM act as string '1' not '1.0'\n```\n\nThe expression given to `ensure` will be `eval [[ $expr ]]` inside `ensure`.\n\n`ensure_not_empty` can test all given args wheather they are not empty, if anyone of them is empty, it will die.\n\n```bash\nsource /path/to/baux/lib/ensure.sh\n\none=1\ntwo=2\nempty=\n\nensure_not_empty \"$one\" \"$two\"  # OK\nensure_not_empty \"$empty\"       # will die\n\necho \"Can not be here.\"\n```\n\nIt is a best practice to wrap each arg with double qoute.\n\n#### Explicit Assertion\n\n`ensure_is \"$1\" \"$2\"` is equivalent to `ensure \"$1 == $2\".`\n\n```bash\nsource /path/to/baux/lib/ensure.sh\n\none=1\n\nensure_is \"$one\" \"1\" \"$one is not 1\"    # OK\nensure_is \"$one\" \"1.0\" \"$one is not 1\"  # will die\n\necho \"Can not be here.\"\n```\n\n`ensure_isnt \"$1\" \"$2\"` is equivalent to `ensure \"$1 != $2\".`\n\n```bash\nsource /path/to/baux/lib/ensure.sh\n\none=1\n\nensure_isnt \"$one\" \"1.0\" \"$one is not 1\"  # OK\nensure_isnt \"$one\" \"1\" \"$one is not 1\"    # will die\n\necho \"Can not be here.\"\n```\n\n#### Implicit Assertion\n\n`ensure_like \"$1\" \"$2\"` is equivalent to `ensure \"$1 =~ $2\"`\n\n```bash\nsource /path/to/baux/lib/ensure.sh\n\nstr=\"This is a test\"\n\nensure_like \"$str\" \"a\" \"$str does not like a\"           # OK\nensure_like \"$str\" \"test\" \"$str does not like test\"     # OK\n\nensure_like \"$str\" \"check\" \"$str does not like check\"   # will die\n\necho \"Can not be here.\"\n```\n\n`ensure_unlike \"$1\" \"$2\"` is equivalent to `ensure \"! $1 =~ $2\"`\n\n```bash\nsource /path/to/baux/lib/ensure.sh\n\nstr=\"This is a test\"\n\nensure_unlike \"$str\" \"TEST\" \"$str like TEST\"    # OK\nensure_unlike \"$str\" \"IS\" \"$str like IS\"        # OK\n\nensure_unlike \"$str\" \"test\" \"$str like test\"    # will die\n\necho \"Can not be here.\"\n```\n\n#### Assertion Switch\n\nThe `BAUX_ENSURE_DEBUG` variable act as a switch to turn on or off the assertion, its default value is `1`, which means turn on assertion, if you want to turn off, you can set `BAUX_ENSURE_DEBUG` to `0` before sourcing the `ensure.sh`.\n\n###  Utility (`utils.sh`)\n\n#### Get Options\n\n```bash\nsource /path/to/baux/lib/utils.sh\n\n# need to declare two associative arrays\n# one for options and one for arguments\n\ndeclare -A opts args\n\n# The first arg is array NAME for options\n# The second arg is array NAME for arguments\n# The third arg is the options string, a letter for an option,\n# letter follow with ':' means a option argument\n# The remain args are needed to be parsed\n\ngetoptions opts args \"n:vh\" \"$@\"\n\n# after getoptions, need to correct the option index\nshift $((OPTIND - 1))\n\n# now you can check options and arguments\n[[ ${opts[h]} -eq 1 ]] \u0026\u0026 echo \"Option 'h' invoke\"\n[[ ${opts[v]} -eq 1 ]] \u0026\u0026 echo \"Option 'v' invoke\"\n[[ ${opts[n]} -eq 1 ]] \u0026\u0026 echo \"Option 'n' invoke, argument is ${args[n]}\"\n\n# an invoked option will be assigned with 1\n# an invoked option with an argument, the argument value will be stored\n```\n\n#### Read Config File\n\n```bash\nsource /path/to/baux/lib/utils.sh\n\n# need to declare an associative array for storing config value\ndeclare -A CONFIGS\n\n# config name and value are seperated with '='\n# strings follow '#' means comment\n# each line allows one name-value pair\n# leading and tailing spaces is allowed\n# spaces on both sides of '=' is allowed, too\n\necho \"NAME=ishbguy\" \u003e\u003emy.config\necho \"EMAIL=ishbguy@hotmail.com\" \u003e\u003emy.config\n\nread_config CONFIGS my.config\n\n# you will notice that all config name will convert to lower case\necho \"my name is ${CONFIGS[name]}\"\necho \"my email is ${CONFIGS[email]}\"\n\nread_config CONFIGS file-not-exsit # will not fail, just return 1\n```\n\n#### Other Utilities\n\n```bash\nsource /path/to/baux/lib/utils.sh\n\ncecho red \"This message will print in red\" # color can be: black, red, green\n                                           # yellow, blue, magenta, cyan, white\n\nrealdir /path/to/script # similar to realpath, this will print /path/to\nrealdir /p1/script1 /p2/script2 # will print /p1 /p2\n\ncheck_tool sed awk realpath # check needed tools in PATH\ncheck_tool tools-not-exsit  # will die\n```\n\n### Debugging (`log.sh, trace.sh`)\n\n`BAUX` has a simple `log` function which can accept a log level and message string args, then print the log mesages to `stdout` or a specified log file.\n\n`BAUX` also has a simple `callstack` function to print out the call stack when encountering error.\n\n#### Logging (`log.sh`)\n\n```bash\nsource /path/to/baux/lib/log.sh\n\n# log has 5 log level and priority from low to high is:\n#\n# debug \u003c info \u003c warn \u003c error \u003c fatal \u003c panic \u003c quiet\n#\n# default log output level is debug, means that the log priority higher than\n# debug will be printed.\n\nlog debug \"This is a log test\"  # this will print a log message to stdout\n\nBAUX_LOG_OUTPUT_LEVEL=info      # set log output level to info\nlog debug \"a debug message\"     # will not print\nlog info \"a info message\"       # will print into stdout\n\n# set a log output file, default is empty which will print into stdout\n# if test.log is not exsit, log will create it\n\nBAUX_LOG_OUTPUT_FILE=test.log   \n\nlog info \"write into a log file\"    # this will write into test.log\n```\n\n#### Callstack (`trace.sh`)\n\n```bash\nsource /path/to/baux/lib/trace.sh\n\n# callstack need a start index of the function stack array\n# if index is 0, which will print also the callstack 0, if index is 1,\n# which will not print callstack line, and start to print from function\n# three.\n\none() {\n    two\n}\ntwo() {\n    three\n}\nthree() {\n    callstack 0\n}\n\none\n```\n\nRun the above test script, will print the callstack to stdout like:\n\n```bash\n+ callstack 0 [./test.sh:16:three]\n  + three [./test.sh:13:two]\n    + two [./test.sh:10:one]\n      + one [./test.sh:19:main]\n```\n\n### Testing (`var.sh, test.sh`)\n\n#### Variable Type Check (`var.sh`)\n\n```bash\nsource /path/to/baux/lib/var.sh\n\ndeclare -a var\n\ntype_array  var \u0026\u0026 echo \"this is an index array\"\ntype_map    var \u0026\u0026 echo \"this is an associative array\"\ntype_int    var \u0026\u0026 echo \"this is an integer var\"\ntype_func   var \u0026\u0026 echo \"this is a function name\"\ntype_ref    var \u0026\u0026 echo \"this is a var reference\"\ntype_export var \u0026\u0026 echo \"this is an exported var\"\ntype_lower  var \u0026\u0026 echo \"var's value has lower case attribute\"\ntype_upper  var \u0026\u0026 echo \"var's value has upper case attribute\"\n```\n\n#### Unit Test (`test.sh`)\n\n`BAUX`'s test functions are similar to `Perl`'s [`Test::More`](https://metacpan.org/pod/Test::More) module.\n\n##### Simple test\n\n```bash\nsource /path/to/baux/lib/test.sh\n\n# ok $expr test is equivalent to [[ $expr ]]\nok '1 == 1' 'Test equal'        # pass\nok '1 != 0' 'Test not equal'    # pass\n\n# is $a $b test is equivalent to [[ $a == $b ]]\nis 1 1 \"Test equal\"             # pass\nis 1 0 \"Test not equal\"         # fail\n\n# isnt $a $b test is equivalent to [[ $a != $b ]]\nisnt 1 1 \"Test equal\"           # fail\nisnt 1 0 \"Test not equal\"       # pass\n\n# like $a $b test is equivalent to [[ $a =~ $b ]]\nlike \"apple\" \"app\" \"Test like\"      # pass\nlike \"apple\" \"App\" \"Test not like\"  # fail\n\n# unlike $a $b test is equivalent to [[ ! $a =~ $b ]]\nunlike \"apple\" \"app\" \"Test like\"      # fail\nunlike \"apple\" \"App\" \"Test not like\"  # pass\n\n# each test status will print when that test finish\n\n# finally, report a summary with the numbers of:\n# total, pass, fail and skip\nsummary\n```\n\n##### Run command test with `run_ok`\n\n```bash\nsource /path/to/baux/lib/test.sh\n\n# run_ok like ok, but run_ok provide $status, $output inside to test the\n# exit status and cmd output. When use these 2 variables, you need to single\n# quote the expr to avoid expanded outside run_ok. And the given cmd is run\n# in a subshell like output=$(eval \"$cmd\" 2\u003e\u00261), you can check both nomral\n# and error message in $output.\n\nrun_ok '$status -eq 0' exit 0       # pass\nrun_ok '$status -eq 1' exit 1       # pass\nrun_ok '$output =~ \"command not found\"' cmd_not_found   # pass\nrun_ok '$output =~ \"hello world\"' echo \"hello world\"    # pass\n\n# you can also do like this for the test statement inside run_ok is equivalent\n# to [[ $expr ]]\n\nrun_ok '$status -eq 0 \u0026\u0026 $(echo $output | wc -l) -eq 1' echo \"test\" # pass\n\nsummary\n```\n\n##### Run `subtest`\n\n`subtest` will group the your tests in a single sub-test, if one of the tests in `subtest` fails, the `subtest` will fail, and the total and fail counters will increase 1.\n\n```bash\nsource /path/to/baux/lib/test.sh\n\n# format like: subtest \"test name\" 'tests cmds'\n\nsubtest 'subtest PASS' \"\n    is 1 1 'test equal'\n    isnt 1 0 'test not equal'\n\"\n\nsummary\n```\n\n##### `skip` a following test\n\n```bash\nsource /path/to/baux/lib/test.sh\n\nis 1 1      # pass\nskip\nisnt 1 1    # this will skip\nisnt 0 1    # this will run and pass\n\nsummary\n```\n\n##### Customize test outputs\n\nYou can customize test's total, pass, fail, skip prompt strings and colors.\n\n```bash\nsource /path/to/baux/lib/test.sh\n\n# these are default prompt strings\nBAUX_TEST_PROMPTS[TOTAL]=\"TOTAL\"\nBAUX_TEST_PROMPTS[PASS]=\"PASS\"\nBAUX_TEST_PROMPTS[FAIL]=\"FAIL\"\nBAUX_TEST_PROMPTS[SKIP]=\"SKIP\"\n\n# these are default colors, you can change color which cecho accept\nBAUX_TEST_COLORS[TOTAL]=\"blue\"\nBAUX_TEST_COLORS[PASS]=\"green\"\nBAUX_TEST_COLORS[FAIL]=\"red\"\nBAUX_TEST_COLORS[SKIP]=\"yellow\"\nBAUX_TEST_COLORS[EMSG]=\"red\"\n```\n\n### Exception (`except.sh`)\n\n### Array (`array.sh`)\n\n### Pattern (`pattern.sh`)\n\n## :hibiscus: Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n\n## :boy: Authors\n\n+ [ishbguy](https://github.com/ishbguy)\n\n## :scroll: License\n\nReleased under the terms of [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fishbguy%2Fbaux","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fishbguy%2Fbaux","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fishbguy%2Fbaux/lists"}