{"id":13879741,"url":"https://github.com/fetlife/scallop","last_synced_at":"2025-04-05T14:09:42.628Z","repository":{"id":34934786,"uuid":"192554624","full_name":"fetlife/scallop","owner":"fetlife","description":"Ergonomic shell wrapper for Ruby.","archived":false,"fork":false,"pushed_at":"2022-02-22T04:56:56.000Z","size":54,"stargazers_count":147,"open_issues_count":2,"forks_count":6,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-03-29T13:11:21.465Z","etag":null,"topics":["gem","ruby","shell"],"latest_commit_sha":null,"homepage":"","language":"Ruby","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/fetlife.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-06-18T14:18:16.000Z","updated_at":"2025-03-14T16:15:46.000Z","dependencies_parsed_at":"2022-08-08T03:00:48.611Z","dependency_job_id":null,"html_url":"https://github.com/fetlife/scallop","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/fetlife%2Fscallop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fetlife%2Fscallop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fetlife%2Fscallop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fetlife%2Fscallop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fetlife","download_url":"https://codeload.github.com/fetlife/scallop/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247345856,"owners_count":20924102,"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":["gem","ruby","shell"],"created_at":"2024-08-06T08:02:31.091Z","updated_at":"2025-04-05T14:09:42.604Z","avatar_url":"https://github.com/fetlife.png","language":"Ruby","readme":"[![Gem Version](https://badge.fury.io/rb/scallop.svg)](https://badge.fury.io/rb/scallop)\n[![CircleCI](https://circleci.com/gh/fetlife/scallop.svg?style=svg)](https://circleci.com/gh/fetlife/scallop)\n[![Maintainability](https://api.codeclimate.com/v1/badges/b7d9660aa51c7205fbac/maintainability)](https://codeclimate.com/github/fetlife/scallop/maintainability)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/b7d9660aa51c7205fbac/test_coverage)](https://codeclimate.com/github/fetlife/scallop/test_coverage)\n\n# Scallop\n\n![](./scallop.png)\n\nErgonomic shell wrapper.\n\nFeatures:\n\n* Easy access to command's output (stdout \u0026 stderr)\n* Failure handling\n* Parameterization\n* Measuring execution time\n* Built-in string escaping\n* No dependencies\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'scallop'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install scallop\n\n## Usage\n\nTo run `sudo -u chuck grep -R /home/chuck`\n\n```ruby\nresult = Scallop.sudo(:chuck).cmd(:grep, '-R', '/home/chuck').run\n```\n\nYou can then check whether command succeeded\n\n```ruby\nresult.success?\n```\n\nSee its output\n\n```ruby\nresult.stdout\nresult.stderr\nresult.output # STDOUT and STDERR combined\n```\n\nYou can also access information about command execution time\n\n```ruby\nresult.timing.real # Elapsed real time\nresult.timing.stime # System CPU time\nresult.timing.utime # User CPU time\nresult.timing.total # Total time, that is utime + stime + cutime + cstime\n```\n\n### Handling failures with exceptions\n\nIf you replace `run` with `run!`, exception will be raised in case command fails\n\n```ruby\nbegin\n  Scallop.cmd(some_command).run!\nrescue Scallop::Errors::CommandFailed =\u003e error\n  # you can access result right on the error itself\n  error.result.stderr\nend\n```\n\n### Piping\n\nTo run `cat /some/file | grep something`\n\n```ruby\ncommand = Scallop.cmd(:cat, '/some/file') | Scallop.cmd(:grep, 'something')\ncommand.run\n```\n\n### Parameterization\n\n```ruby\nstored_command = Scallop.cmd(:rm, '-rf', Scallop::Param[:path])\n\nstored_command.set(path: '/foo').run # rm -rf /foo\nstored_command.set(path: '/bar').run # rm -rf /bar\n```\n\n--------\n\nYou can also [check specs](./spec/scallop_spec.rb) for examples.\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffetlife%2Fscallop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffetlife%2Fscallop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffetlife%2Fscallop/lists"}