{"id":16788591,"url":"https://github.com/mna/luashell","last_synced_at":"2025-07-31T00:33:01.800Z","repository":{"id":145701744,"uuid":"278185113","full_name":"mna/luashell","owner":"mna","description":"A small Lua module to help write what would be shell scripts in Lua. (mirror)","archived":false,"fork":false,"pushed_at":"2021-05-19T17:09:48.000Z","size":38,"stargazers_count":13,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-10T23:14:24.506Z","etag":null,"topics":["lua","mirror","shell"],"latest_commit_sha":null,"homepage":"https://git.sr.ht/~mna/luashell","language":"Lua","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mna.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":["mna"],"custom":["https://www.buymeacoffee.com/mna"]}},"created_at":"2020-07-08T20:11:56.000Z","updated_at":"2025-03-13T17:53:50.000Z","dependencies_parsed_at":"2023-07-02T09:21:54.459Z","dependency_job_id":null,"html_url":"https://github.com/mna/luashell","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/mna/luashell","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mna%2Fluashell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mna%2Fluashell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mna%2Fluashell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mna%2Fluashell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mna","download_url":"https://codeload.github.com/mna/luashell/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mna%2Fluashell/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267966465,"owners_count":24173549,"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","status":"online","status_checked_at":"2025-07-30T02:00:09.044Z","response_time":70,"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":["lua","mirror","shell"],"created_at":"2024-10-13T08:18:23.250Z","updated_at":"2025-07-31T00:33:01.731Z","avatar_url":"https://github.com/mna.png","language":"Lua","funding_links":["https://github.com/sponsors/mna","https://www.buymeacoffee.com/mna"],"categories":[],"sub_categories":[],"readme":"# luashell\n\nThis is a small Lua module to help write what would be shell scripts in Lua. It provides easy ways to run commands and check for success, get values of environment variables with optional default value if not set, capture output of commands, run pipelines and run POSIX tests (e.g. if file exists, if directory exists, etc.).\n\nIt has a single external dependency, [luaposix], and as such only works on POSIX systems. Otherwise it uses the `os`, `string` and `table` standard libraries.\n\n* Canonical repository: https://git.sr.ht/~mna/luashell\n* Issue tracker: https://todo.sr.ht/~mna/luashell\n\n## Install\n\nVia Luarocks:\n\n```\n$ luarocks install luashell\n```\n\nOr simply copy the single shell.lua file in your project or your `LUA_PATH`.\n\n## API\n\nAssuming `local sh = require 'shell'`. You can check out `shell_test.lua` for\nactual examples of using the API.\n\n### sh.exec(...)\n\nAlias: `sh(...)`.\n\nRun the command specified as first argument, passing along any additional argument. The first argument can be a string, a `Cmd` or a `Pipe`. Returns true or false based on exit code of the command, and the status and code as additional return values. Status is one of 'exited', 'killed' or 'stopped'.\n\n### sh.var(t)\n\nReturn the value of the environment variable. If t is a table\ninstead of a string, then it returns the first non-empty string\nvalue if the initial environment variable name is not set.\n\n### sh.type(v)\n\nReturn the type of v, which expands the built-in `type` Lua\nfunction to include 'Shell', 'Cmd' and 'Pipe' instances.\n\n### sh.cmd(...)\n\nCreate a 'Cmd' instance using the provided arguments. The first\nargument is the command name and the rest are the arguments bound\nto that 'Cmd'.\n\n### sh.test(s)\n\nExecute a test with the specified condition. This is a shortcut\nfor `sh.cmd('test', ...):exec()` and only works for cases where\nno quoting is required, as it simply splits the condition on\nwhitespace to extract the list of arguments. For more complex\ncases, using the 'Cmd' is required.\n\n### sh.glob(s)\n\nThis is the same as the luaposix `posix.glob` function, except that it\nexpands the resulting table so that it returns each match as a\ndistinct value, ready to be used in e.g. `Shell.exec`.\n\n### Cmd:exec(...)\n\nExecute the 'Cmd' with optional additional arguments. Returns a boolean\nindicating success (exit code 0), and the status string and code. The\nstatus string is the same as the one in luaposix, that is:\n\"exited\", \"killed\" or \"stopped\". The code is the exit code or the signal\nnumber responsible for \"killed\" or \"stopped\".\n\n### Cmd:output(...)\n\nThis is the same as `Cmd:exec` except that it returns the stdout output as a string\ninstead of the true/false boolean. The rest of the returned values are the same.\nIf the command failed and no output was generated on stdout, it returns nil as output,\nso that it can be used in an `assert` call. Trailing newlines are removed.\n\n### Cmd:redirect(target, truncate, ...)\n\nThis is similar to `Cmd:exec` and `Cmd:output`, but it redirects the stdout output\nof the command to the specified target. The target can be:\n\n* a string, in which case this is a filename that will be open in append (default)\n  or truncate (if truncate is true) mode and will be closed on return.\n* a file handle (`io.type(target) == 'file'`), in which case the truncate argument is\n  ignored and the output will be written to that file handle. It is not closed on\n  return, as the function did not open it.\n* a number, in which case this is a file descriptor to which the output will be\n  written, and in which case the truncate argument is ignored. It is not closed on\n  return, as the function did not open it.\n* a function, in which case it will be called with one argument, a string with each chunk\n  of bytes from the output. It will be called a final time with nil to indicate the last\n  call. The truncate argument is ignored in that case too.\n\nThe rest of the arguments are extra arguments for the command, as for `Cmd:exec` and\n`Cmd:output`. It returns true or false as first argument, then the\nstatus and exit code, like `Cmd:exec`.\n\n### Pipe '|' operator\n\nApplying the pipe '|' operator to 'Cmd' or 'Pipe' (or a combination of those)\nresults in a 'Pipe' with those commands, flattened.\n\n### Pipe:exec(...)\n\nExecute the 'Pipe' with optional additional arguments to be provided to the\nfirst command of the pipeline. Returns a boolean\nindicating success (exit code 0), and the status string and code. The\nstatus string is the same as the one in luaposix, that is:\n\"exited\", \"killed\" or \"stopped\". The code is the exit code or the signal\nnumber responsible for \"killed\" or \"stopped\".\n\nNote that the pipeline succeeds unless the final command fails (that is, there\nis no \"set -o pipefail\" mode, this is a bash-specific feature).\n\n### Pipe:output(...)\n\nThis is the same as `Pipe:exec` except that it returns the stdout output as a string\ninstead of the true/false boolean. The rest of the returned values are the same.\nIf the pipe failed and no output was generated on stdout, it returns nil as output,\nso that it can be used in an `assert` call. Trailing newlines are removed.\n\n### Pipe:redirect(target, truncate, ...)\n\nThis is similar to `Pipe:exec` and `Pipe:output`, but it redirects the stdout output\nof the pipeline to the specified target. The target can be:\n\n* a string, in which case this is a filename that will be open in append (default)\n  or truncate (if truncate is true) mode and will be closed on return.\n* a file handle (`io.type(target) == 'file'`), in which case the truncate argument is\n  ignored and the output will be written to that file handle. It is not closed on\n  return, as the function did not open it.\n* a number, in which case this is a file descriptor to which the output will be\n  written, and in which case the truncate argument is ignored. It is not closed on\n  return, as the function did not open it.\n* a function, in which case it will be called with one argument, a string with each chunk\n  of bytes from the output. It will be called a final time with nil to indicate the last\n  call. The truncate argument is ignored in that case too.\n\nThe rest of the arguments are extra arguments for the pipeline, as for `Pipe:exec` and\n`Pipe:output`. It returns true or false as first argument, then the\nstatus and exit code, like `Pipe:exec`.\n\n## Development\n\nClone the project and install the required development dependencies:\n\n* luaposix (the only run-time dependency)\n* luaunit (unit test runner)\n* luacov (recommended, test coverage)\n* inspect (recommended for debugging, pretty-printing of values)\n* luabenchmark (to run benchmarks)\n\nIf like me you prefer to keep your dependencies locally, per-project, then I recommend using my [llrocks] wrapper of the `luarocks` cli, which by default uses a local `lua_modules/` tree.\n\n```\n$ llrocks install ...\n```\n\nTo run tests and benchmarks:\n\n```\n$ llrocks run shell_test.lua\n$ llrocks run shell_bench.lua\n```\n\nTo view code coverage:\n\n```\n$ llrocks cover shell_test.lua\n```\n\n## License\n\nThe [BSD 3-clause][bsd] license.\n\n[luaposix]: https://github.com/luaposix/luaposix\n[bsd]: http://opensource.org/licenses/BSD-3-Clause\n[llrocks]: https://git.sr.ht/~mna/llrocks\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmna%2Fluashell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmna%2Fluashell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmna%2Fluashell/lists"}