{"id":25921921,"url":"https://github.com/binaryphile/mk.bash","last_synced_at":"2026-06-08T19:04:37.195Z","repository":{"id":280049188,"uuid":"626644738","full_name":"binaryphile/mk.bash","owner":"binaryphile","description":"a tiny library for creating project-level scripts that group subcommands like Makefiles","archived":false,"fork":false,"pushed_at":"2026-06-03T05:30:34.000Z","size":53,"stargazers_count":2,"open_issues_count":4,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-03T07:26:12.620Z","etag":null,"topics":[],"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/binaryphile.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,"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":"2023-04-11T22:11:02.000Z","updated_at":"2026-06-03T05:30:38.000Z","dependencies_parsed_at":null,"dependency_job_id":"21d1918c-3f2c-4671-b5f1-e99a2c0dab5f","html_url":"https://github.com/binaryphile/mk.bash","commit_stats":null,"previous_names":["binaryphile/mk.bash"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/binaryphile/mk.bash","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binaryphile%2Fmk.bash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binaryphile%2Fmk.bash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binaryphile%2Fmk.bash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binaryphile%2Fmk.bash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/binaryphile","download_url":"https://codeload.github.com/binaryphile/mk.bash/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binaryphile%2Fmk.bash/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34076032,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2025-03-03T16:16:45.772Z","updated_at":"2026-06-08T19:04:37.191Z","avatar_url":"https://github.com/binaryphile.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mk.bash - Project-Level Command Scripting\n\n![version](badges/version.svg) ![lines](badges/lines.svg) ![tests](badges/tests.svg) ![coverage](badges/coverage.svg)\n\n## Overview\n\n`mk.bash` is a minimalistic framework for creating Bash scripts that offer subcommands.\nThat is to say, it allows you to easily create a script that contains multiple commands that\ncan be specified at runtime.  For example, if my script is called `mk`, it could offer\n`build` and `clean` subcommands that run the appropriate build tools for the project, much\nlike `make`.\n\nIt is useful for grouping sets of related commands, for example, commands that are specific\nto a project and working with its files.\n\nWhy Bash? With Bash, you don't have limitations on your ability to use the language.  This\nmakes it friendly to cutting and pasting shell code from web site examples, for example.\nStaying close to the shell means having access to the same interface that is available\nuniversally to manage Unix systems, and the power that requires.\n\n`mk.bash` helps you write scripts by handling these concerns:\n\n- a simple convention to define subcommands as regular Bash functions\n- safe expansion mode (`IFS=$'\\n'`, `set -o noglob`) so variable expansions require less quotation\n- built-in `--help`, `--version`, and `--trace` flags\n- logging with `mk.Debug`, `mk.Info`, `mk.Error` and `mk.Fatal` for consistent output\n\n## Getting Started\n\n### Installation\n\nCopy `mk.bash` to `~/.local/lib/mk.bash`.\n\n### Creating a Command Script\n\n1.  Create a script file in your project directory and `chmod +x` it.  Name it what you\n    like.  We'll use `mk` for our examples.\n\n2.  Define `Prog`, `Usage_` and optionally `Version` as global variables.  Use `mk.SetProg`,\n    `mk.SetUsage` and `mk.SetVersion` to register them with the library.\n\n3.  Implement subcommands as Bash functions, like `cmd.build()` or `cmd.clean()`.\n\n4.  Ensure the boilerplate is at the end of the script, which sources `mk.bash` and calls\n    `mk.Main`.  Update the `source` directive with the directory for `mk.bash`.\n\n`mk.Main` runs the selected subcommand.  It echoes the program name and version, if defined,\nand then runs the subcommand's function.  The subcommand's function is simply the\nsubcommand name, prefixed with `cmd.`.  This allows you to use subcommand names that\nwould otherwise conflict with built-in commands you may need, such as `install`.\n\n### Example\n\n``` bash\n#!/usr/bin/env bash\n\nProg=$(basename \"$0\")   # match what the user called\nVersion=0.1\n\nread -rd '' Usage_ \u003c\u003cEND\nUsage:\n\n  $Prog clean\n\n  clean -- removes temporary files like build artifacts and cache files.\nEND\n\n## commands\n\ncmd.clean() {\n  # Cue echoes the supplied command, then runs it\n  mk.Cue find . -type f \\( -name '*.tmp' -o -name '*.log' -o -name '*.cache' \\) -delete\n}\n\n## boilerplate\n\nsource ~/.local/lib/mk.bash 2\u003e/dev/null || { echo 'fatal: mk.bash not found' \u003e\u00262; exit 1; }\n\n# enable safe expansion\nIFS=$'\\n'\nset -o noglob\n\nmk.SetProg $Prog\nmk.SetUsage \"$Usage_\"\nmk.SetVersion $Version\n\nreturn 2\u003e/dev/null        # stop if sourced, for interactive debugging\nmk.HandleOptions \"$@\"    # standard options\nmk.Main \"${@:$?}\"         # showtime\n```\n\n## Using Your Script\n\n```bash\n$ mk clean\nmk version 0.1\n\nfind . -type f \\( -name '*.tmp' -o -name '*.log' -o -name '*.cache' \\) -delete\n\n$ mk --help\nUsage:\n\n  mk clean\n\n  clean -- removes temporary files like build artifacts and cache files.\n```\n\n## Debugging\n\nUse `-x` or `--trace` for tracing.\n\n```bash\n$ mk -x clean\n[trace output not shown]\n```\n\n## Utility Functions\n\n### `mk.Cue` - Echo and Execute\n\nDisplays commands in yellow while running them, to differentiate from command output.\n\n```bash\n$ mk.Cue echo \"Hello, World!\"\necho Hello, World! # \u003c- in yellow\nHello, World!\n```\n\n### `mk.Each` - Apply a Command to Each Line of Input\n\nTakes an argument for a command to run and iterates over each line of input, running the\ncommand with the line as arguments:\n\n```bash\n# symlink shell rc files to visible names\nmk.Each 'ln -sf' \u003c\u003cEND\n  ~/.bashrc ~/bashrc\n  ~/.bash_profile ~/bash_profile\nEND\n```\n\n### `mk.KeepIf` - Filter Input by Condition\n\nFilter items based on feeding them to a boolean function.\n\n```bash\n$ startsWithA() { [[ $1 == a* ]]; }\n$ echo -e \"apple\\nbanana\\ncherry\" | mk.KeepIf startsWithA\napple\n```\n\n## Debugging \u0026 Logging\n\nOutput messages on stderr with the log level prepended.\n\n- `mk.Debug \"message\"` (only logs if debug is enabled via `mk.SetDebug on`)\n- `mk.Info \"message\"`\n- `mk.Error \"message\"`\n- `mk.Fatal \"message\" [exit code]` (exits with error)\n\n## License\n\nThis project is open-source under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinaryphile%2Fmk.bash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbinaryphile%2Fmk.bash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinaryphile%2Fmk.bash/lists"}