{"id":21703844,"url":"https://github.com/shinokada/shellscript-starter","last_synced_at":"2025-07-30T12:09:46.853Z","repository":{"id":65103704,"uuid":"442618806","full_name":"shinokada/shellscript-starter","owner":"shinokada","description":"Quick starter for Shell/Bash script","archived":false,"fork":false,"pushed_at":"2024-06-09T07:36:22.000Z","size":91,"stargazers_count":17,"open_issues_count":1,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-12T15:12:50.625Z","etag":null,"topics":["bash-script","shell-script"],"latest_commit_sha":null,"homepage":"https://shellscript-starter.codewithshin.com/","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/shinokada.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}},"created_at":"2021-12-29T00:32:22.000Z","updated_at":"2024-07-14T00:14:42.000Z","dependencies_parsed_at":"2024-05-16T05:14:37.927Z","dependency_job_id":"385e30e1-68f5-45eb-9d55-c85720f78632","html_url":"https://github.com/shinokada/shellscript-starter","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shinokada%2Fshellscript-starter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shinokada%2Fshellscript-starter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shinokada%2Fshellscript-starter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shinokada%2Fshellscript-starter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shinokada","download_url":"https://codeload.github.com/shinokada/shellscript-starter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248586246,"owners_count":21128998,"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-script","shell-script"],"created_at":"2024-11-25T21:35:57.867Z","updated_at":"2025-04-12T15:12:56.873Z","avatar_url":"https://github.com/shinokada.png","language":"Shell","funding_links":["https://ko-fi.com/Z8Z2CHALG'"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\u003ca href='https://ko-fi.com/Z8Z2CHALG' target='_blank'\u003e\u003cimg height='42' style='border:0px;height:42px;' src='https://storage.ko-fi.com/cdn/kofi3.png?v=3' alt='Buy Me a Coffee at ko-fi.com' /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eShellscript Starter\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://shellscript-starter.codewithshin.com/\"\u003eShellscript Starter\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://twitter.com/shinokada\" rel=\"nofollow\"\u003e\u003cimg src=\"https://img.shields.io/badge/created%20by-@shinokada-4BBAAB.svg\" alt=\"Created by Shin Okada\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opensource.org/licenses/MIT\" rel=\"nofollow\"\u003e\u003cimg src=\"https://img.shields.io/github/license/shinokada/shellscript-starter\" alt=\"License\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## Getting started\n\nClone or download the repo.\n\n[Read more details](https://medium.com/mkdir-awesome/a-shell-script-starter-for-small-to-large-projects-d9996f0cce83)\n\n## What in this?\n\n- Unit test\n- Structure\n- Sample commands\n- Utils (text, banner)\n- Shell and Bash helpers\n\n## Shebang\n\nSelect one of the followings for the `shellscript_starter`:\n\n```\n#!/usr/bin/env bash\n#!/usr/bin/env zsh\n#!/usr/bin/env ksh\n#!/usr/bin/env bash\n#!/bin/sh\n```\n\n## Changing the main script name\nThe main script name is shellscript_starter. You need to change it to a unique name.\n\n```\n# change the directory name\n$ mv shellscript_starter my_script\n$ cd my_script\n# change the main script name\n$ mv shellscript_starter my_script\n```\n\nTest some commands:\n\n```\n$ ./my_script -h\n$ ./my_script cmd1 -a -b\n$ ./my_script --version\n$ ./my_script text_example\n```\n\nMake the file executable:\n\n```\n$ chmod +x my_script\n```\n\n## Setting variables\nIn the main script, shellscript_starter file, find the variable section, and set your variables:\n\n## Importing files\nIn the import files section, you will find example codes. You need to import `/lib/getoptions.sh` and `/lib/main_definition.sh` for it to work properly.\n\nIf you are going to use subcommands, create new definition files in the `lib` directory and import those files here. More about definition files later.\n\nYou don’t need to import your subcommand files here. We will do it in the case statement later.\n\nThe repo includes the `utils` , `shell_helpers` , and `bash_helpers` files.\n\n```\n# Import files\n# shellcheck disable=SC1091\n{\n    . \"${script_dir}/lib/getoptions.sh\"\n    . \"${script_dir}/lib/main_definition.sh\"\n    . \"${script_dir}/lib/utils.sh\"\n    . \"${script_dir}/lib/cmd1_definition.sh\"\n    . \"${script_dir}/lib/cmd2_definition.sh\"\n    # import only one of helpers file\n    # . \"${script_dir}/lib/shell_helpers.sh\"\n    # or\n    # . \"${script_dir}/lib/bash_helpers.sh\"\n}\n```\n\n### utils.sh\nYou can use the utils file for all Shells. It has check_cmd, check_bash, text colors and text attribute functions.\n\n### shell_helpers.sh and bash_helpers.sh\nUse one of those helper files for your project. If your target is Bash, then import bash_helpers.sh, otherwise, import shell_helpers.sh.\n\n### cmd1_definition.sh, cmd2_definition.sh\nThese are sample codes. Please use them as references when you create yours.\n\n## Creating subcommand definition files\nCreate your parser definition files in the /lib directory. See the /lib/cmd1_definition.sh and /lib/cmd2_definition.sh as examples. In your definition files, set command flags, parameters, options, descriptions, and examples.\n\nThe following example is from ko1nksm/getoptions.\n\n```\nparser_definition_cmd1() {\n    # from https://github.com/ko1nksm/getoptions/blob/master/examples/basic.sh\n    setup REST plus:true help:usage abbr:true -- \\\n        \"Usage: ${2##*/} [options...] [arguments...]\" ''\n    msg -- 'getoptions basic example' ''\n    msg -- 'Options:'\n    flag FLAG_A -a -- \"message a\"\n    flag FLAG_B -b -- \"message b\"\n    flag FLAG_F -f +f --{no-}flag -- \"expands to --flag and --no-flag\"\n    flag FLAG_W --with{out}-flag -- \"expands to ---with-flag and --without-flag\"\n    flag VERBOSE -v --verbose counter:true init:=0 -- \"e.g. -vvv is verbose level 3\"\n    param PARAM -p --param pattern:\"foo | bar\" -- \"accepts --param value / --param=value\"\n    param NUMBER -n --number validate:number -- \"accepts only a number value\"\n    option OPTION -o --option on:\"default\" -- \"accepts -ovalue / --option=value\"\n    disp :usage -h --help\n}\n```\n\n## Checking user environment\n\n### OS\nYou will find the following code in the shellscript_starter file. If you need to check the OS, you can use it to set OS-dependent variables or commands. Otherwise, you can remove it.\n\n```\n# CHECK ENVIRONMENT\n# If you need to check OS uncomment this\nif [ \"$(uname)\" = \"Linux\" ]; then\n#   do something\n    echo \"Your OS is Linux.\"\nelif [ \"$(uname)\" = \"Darwin\" ]; then\n#   do something else\n    echo \"Your OS is mac.\"\nfi\n```\n\n### check commands\nThe /lib/utils.sh file has check_cmd() function. Once you imported this file in the import section, you can check if the user has certain commands:\n\n```\ncheck_cmd jq\ncheck_cmd you_dont_have_it\n```\n\n### check bash\nIf your target is Bash, then it is a good idea to check the bash version.\n\nThe utils file has the check_bash() command. Check if a user has at least Bash version of 5:\n\n```\ncheck_bash 5\n```\n\n## Adding a subcommand\nLet’s create a new subcommand called create.\n\n### Step 1\nAdd your command in the /lib/main_definition.sh file.\n\n```\n# example\ncmd create -- \"Create this and that.\"\n```\n\n### Step 2\nCreate the lib/create_definition.sh file and import it in the above import section.\n\n```\n# in the import section\n. \"${script_dir}/lib/create_definition.sh\"\n```\n\n```\nparser_definition_create() {\n    setup REST plus:true help:usage abbr:true -- \\\n        \"Usage: ${2##*/} [options...] [arguments...]\" ''\n    msg -- 'create example' ''\n    msg -- 'Options:'\n    flag FLAG_A -a -- \"message a\"\n    param PARAM -d --dir -- \"accepts --dir value / --dir=value\"\n    disp :usage -h --help\n}\n```\n\n### Step 3\nCreate /src/create.sh and write your script.\n\n```\nfn_create() {\n    # sample code\n    echo \"FLAG_A: $FLAG_A\"\n    echo \"PARAM: $PARAM\"\n    echo \"My variable VAR1: $VAR1.\"\n\n    i=0\n    while [ $# -gt 0 ] \u0026\u0026 i=$((i + 1)); do\n        echo \"$i: $1\"\n        shift\n    done\n}\n```\n\n### Step 4\nAt the end of the main script, shellscript_starter file, you will find examples.\n\n```\ncmd1)\n    eval \"$(getoptions parser_definition_cmd1 parse \"$0\")\"\n    parse \"$@\"\n    eval \"set -- $REST\"\n    # shellcheck disable=SC1091\n    . \"${script_dir}/src/cmd1.sh\"\n    fn_cmd1 \"$@\"\n    ;;\ncmd2)\n    eval \"$(getoptions parser_definition_cmd2 parse \"$0\")\"\n    parse \"$@\"\n    eval \"set -- $REST\"\n    # shellcheck disable=SC1091\n    . \"${script_dir}/src/cmd2.sh\"\n    fn_cmd2 \"$@\"\n    ;;\n```\n\nWe are adding the following:\n\n```\nYour new subcommand is: create \nYour parser definition file is: lib/create_definition\nThe lib/cmd3_definition file has: parser_definition_create() function\nThe src/cmd3.sh file has: a function fn_create()\nAdd the following:\n```\n\n```\ncreate)\n    eval \"$(getoptions parser_definition_create parse \"$0\")\"\n    parse \"$@\"\n    eval \"set -- $REST\"\n    # shellcheck disable=SC1091\n    . \"${script_dir}/src/create.sh\"\n    fn_create \"$@\"\n    ;;\n```\n\n### Step 5 Test your script\n\n```\n$ ./shellscript_starter create -a -d ~/Downloads\n```\n\n## Example commands\nThe starter repo includes three subcommands.\n\n### Text example\nThis subcommand prints different text colors and types.\n\n```\n$ ./shellscript_starter text_example\n```\n\nThe /src/text_example.sh file uses functions from the /lib/utils.sh that you can use for your project.\n\n### cmd1\n\nThis subcommand uses the ko1nksm/getoptions basic example.\n\n```\n$ ./shellscript_starter cmd1 -a -b +f --with-flag -vvv -p foo -n 5\n```\n\n### cmd2\n\nThis subcommand uses the ko1nksm/getoptions advanced example.\n\n```\n$ ./shellscript_starter cmd2 -a +b -c -vv -p bar --number 5 --range 50 --pattern foo --blood-type ab --array a,b,c,d --array-posix e,f,g arg1\n```\n\n## Helper files\nThe starter repo includes two helper files. Import only one of the helper files.\n\n```\n# shellcheck disable=SC1091\n{\n    # other files ...\n    . \"${script_dir}/lib/shell_helpers.sh\"\n}\n```\n\n## Debian APT\n\nIf you are creating a Debian package, you need to remove the readlinkf() function and define the script directory as in the following:\n\n```\nscript_dir=\"/usr/share/my_script\"\n```\n\n## Unit testing\n\nThe starter uses Shellspec unit testing.\n\nWhen you run a unit test for bash_helpers_spec.sh, specify the path to bash using the -s parameter.\n\n```\n$ shellspec spec/bash_helpers_spec.sh -s \"/usr/bin/env bash\"\n```\n\n\n## Credits\n\n- [Shellspec](https://github.com/shellspec/shellspec) for unit testing\n- [getoptions](https://github.com/ko1nksm/getoptions) for option parser\n- [readlinkf](https://github.com/ko1nksm/readlinkf) for POSIX compliant readlink -f\n- [Bash helpers](https://github.com/dylanaraps/pure-bash-bible)\n- [Shell helpers](https://github.com/dylanaraps/pure-sh-bible)\n- [Banners](https://github.com/yousefvand/shellman)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshinokada%2Fshellscript-starter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshinokada%2Fshellscript-starter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshinokada%2Fshellscript-starter/lists"}