{"id":47827901,"url":"https://github.com/standardbeagle/ps-bash","last_synced_at":"2026-04-03T20:02:47.471Z","repository":{"id":348866174,"uuid":"1200151021","full_name":"standardbeagle/ps-bash","owner":"standardbeagle","description":"Bash commands for PowerShell — real flags, real output, typed objects underneath. 67 commands, 775 tests, cross-platform.","archived":false,"fork":false,"pushed_at":"2026-04-03T12:19:18.000Z","size":304,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-03T13:26:00.844Z","etag":null,"topics":["bash","cli","cross-platform","devops","linux","macos","pipeline","powershell","powershell-module","shell","typed-objects","windows"],"latest_commit_sha":null,"homepage":"https://standardbeagle.github.io/ps-bash/","language":"PowerShell","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/standardbeagle.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":"2026-04-03T04:59:40.000Z","updated_at":"2026-04-03T12:19:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/standardbeagle/ps-bash","commit_stats":null,"previous_names":["standardbeagle/ps-bash"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/standardbeagle/ps-bash","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/standardbeagle%2Fps-bash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/standardbeagle%2Fps-bash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/standardbeagle%2Fps-bash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/standardbeagle%2Fps-bash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/standardbeagle","download_url":"https://codeload.github.com/standardbeagle/ps-bash/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/standardbeagle%2Fps-bash/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31374055,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T17:53:18.093Z","status":"ssl_error","status_checked_at":"2026-04-03T17:53:17.617Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["bash","cli","cross-platform","devops","linux","macos","pipeline","powershell","powershell-module","shell","typed-objects","windows"],"created_at":"2026-04-03T20:02:45.532Z","updated_at":"2026-04-03T20:02:47.453Z","avatar_url":"https://github.com/standardbeagle.png","language":"PowerShell","readme":"# PsBash\n\n**Real bash commands. Real PowerShell objects.**\n\n[![CI](https://github.com/standardbeagle/ps-bash/actions/workflows/ci.yml/badge.svg)](https://github.com/standardbeagle/ps-bash/actions/workflows/ci.yml)\n[![PSGallery](https://img.shields.io/powershellgallery/v/PsBash.svg?label=PSGallery)](https://www.powershellgallery.com/packages/PsBash)\n[![Tests](https://img.shields.io/badge/tests-776%20passing-brightgreen.svg)](#testing)\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n[![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](#cross-platform)\n[![Docs](https://img.shields.io/badge/docs-standardbeagle.github.io%2Fps--bash-blue.svg)](https://standardbeagle.github.io/ps-bash/)\n\n```powershell\nInstall-Module PsBash\n```\n\n\u003cpicture\u003e\n  \u003csource srcset=\"docs/assets/demo.webp\" type=\"image/webp\"\u003e\n  \u003cimg src=\"docs/assets/demo.gif\" alt=\"ps-bash demo showing typed pipeline objects\" width=\"800\"\u003e\n\u003c/picture\u003e\n\n## Why PsBash?\n\nPowerShell ships aliases for `ls`, `cat`, `sort`, `rm` -- but they're lies. `rm -rf` fails. `ls -la` fails. `sort -k3 -rn` fails. They're `Get-ChildItem`, `Get-Content`, and `Sort-Object` wearing a disguise, rejecting every bash flag you throw at them.\n\nPsBash makes the flags work -- and goes further. Every command returns **typed .NET objects** while producing bash-identical text output.\n\n### 1. Parse process data without awk\n\n```powershell\n# Before: string parsing\nPS\u003e Get-Process | Format-Table -Auto | Out-String | ForEach-Object { $_ -split \"`n\" } |\n\u003e\u003e   Where-Object { $_ -match 'pwsh' }\n# Good luck extracting CPU from that\n\n# After: typed objects through the entire pipeline\nPS\u003e $top = ps aux | sort -k3 -rn | head 5\nPS\u003e $top[0].ProcessName   # pwsh\nPS\u003e $top[0].CPU           # 12.4     (decimal, not a string)\nPS\u003e $top[0].PID           # 1847     (integer, not a substring)\nPS\u003e $top | Where-Object { $_.CPU -gt 5.0 } | ForEach-Object { Stop-Process $_.PID -WhatIf }\n```\n\n### 2. Pipeline bridge: objects survive grep and sort\n\n```powershell\nPS\u003e ls -la | grep '.ps1' | sort -k5 -h\n\n-rw-r--r-- 1 beagle wheel     4521 Apr  2 00:57 PsBash.psd1\n-rw-r--r-- 1 beagle wheel    89234 Apr  2 09:46 PsBash.Tests.ps1\n-rw-r--r-- 1 beagle wheel   141234 Apr  2 09:46 PsBash.psm1\n\n# grep matched the TEXT, but passed through the TYPED OBJECTS:\nPS\u003e $files = ls -la | grep '.ps1' | sort -k5 -h\nPS\u003e $files[0].GetType().Name       # PSCustomObject (LsEntry)\nPS\u003e $files.Name                    # PsBash.psd1, PsBash.Tests.ps1, PsBash.psm1\nPS\u003e $files.SizeBytes | Measure-Object -Sum | Select -Expand Sum\n234989\n```\n\n### 3. Built-in jq, awk, sed -- no external binaries\n\n```powershell\nPS\u003e echo '{\"db\":\"postgres\",\"port\":5432}' | jq '.db'\n\"postgres\"\n\nPS\u003e cat app.log | grep ERROR | awk '{print $1, $3}' | sort | uniq -c | sort -rn | head 5\n      47 2024-01-15 DatabaseError\n      23 2024-01-15 TimeoutError\n      12 2024-01-15 AuthError\n\nPS\u003e find . -name '*.log' -mtime +7 | xargs rm -f    # actually works on Windows\n```\n\n## Feature Comparison\n\n| | **PsBash** | **Git Bash** | **Cygwin** | **WSL** | **Crescendo** |\n|---|---|---|---|---|---|\n| Install | `Install-Module` | Git for Windows | 50+ packages | Hyper-V/WSL2 | Per-command XML |\n| Footprint | **340 KB**, 3 files | ~300 MB (MSYS2 runtime) | ~1-4 GB | ~1-15 GB (full distro) | Module + your wrappers |\n| `rm -rf` works | Yes | Yes | Yes | Yes | If you configure it |\n| Typed objects | Always | Never (strings) | Never (strings) | Never (strings) | If configured |\n| Object pipeline | Types survive `grep \\| sort \\| head` | Strings only | Strings only | Strings only | Varies |\n| PowerShell integration | Native -- objects flow into cmdlets | Separate shell | Separate shell | Separate shell | Native |\n| Cross-platform | Win/Lin/Mac | Windows only | Windows only | Windows only | Win/Lin/Mac |\n| Commands | 68 built-in | ~80 (GNU coreutils) | ~200+ (full GNU) | All of Linux | Define your own |\n| jq/awk/sed | Built-in, zero binaries | awk/sed yes, jq no | Yes (install pkg) | Yes (apt install) | Not included |\n| PATH conflicts | None (AllScope aliases) | Shadows PowerShell | Shadows PowerShell | Filesystem boundary | None |\n| Startup overhead | ~100 ms (module load) | New process per call | New process per call | ~1s (cold), ~200ms (warm) | ~100 ms |\n\n## Quick Start\n\n```powershell\n# Install from PSGallery\nInstall-Module PsBash\n\n# Or clone for development\ngit clone https://github.com/standardbeagle/ps-bash.git\nImport-Module ./ps-bash/src/PsBash.psd1\n```\n\n68 bash commands work immediately:\n\n```powershell\nls -la                                    # LsEntry objects\nps aux | sort -k3 -rn | head 5           # PsEntry objects, sorted by CPU\ncat README.md | grep 'bash' | wc -l      # WcResult with .Lines, .Words, .Bytes\nfind . -name '*.ps1' -type f             # FindEntry objects\necho '{\"a\":1}' | jq '.a'                 # built-in JSON processor\ndu -sh * | sort -rh | head 10            # DuEntry objects, human-readable sizes\nsed -i 's/foo/bar/g' config.txt          # in-place file editing\ntar -czf backup.tar.gz src/              # compression with .NET streams\n```\n\n### Permanent Setup\n\n```powershell\n# Add to your PowerShell profile\nAdd-Content $PROFILE \"`nImport-Module PsBash\"\n```\n\n## How It Works\n\nEvery PsBash command returns a PSCustomObject with a `.BashText` property. The terminal renders BashText (looks like real bash). Your code accesses typed properties.\n\n```\n  ls -la\n    |\n  Invoke-BashLs\n    |\n  [LsEntry] objects\n    .Name         = \"README.md\"\n    .SizeBytes    = 4521             [int]\n    .Permissions  = \"-rw-r--r--\"     [string]\n    .Owner        = \"beagle\"         [string]\n    .LastModified = 2024-04-02...    [DateTime]\n    .BashText     = \"-rw-r--r-- 1 beagle wheel  4521 Apr  2 ...\"\n```\n\nPipeline commands (`grep`, `sort`, `head`, `tail`, `tee`) match against BashText but pass through the **original typed objects**. This is the pipeline bridge -- the core architectural pattern.\n\n## 68 Commands\n\n| Category | Commands |\n|----------|----------|\n| **Listing** | `ls` `find` `stat` `tree` `du` `pwd` `basename` `dirname` |\n| **Files** | `cp` `mv` `rm` `mkdir` `rmdir` `touch` `ln` |\n| **Content** | `cat` `head` `tail` `tac` `wc` `nl` `rev` `strings` `fold` `expand` `unexpand` `split` |\n| **Search** | `grep` `rg` |\n| **Text** | `sed` `awk` `cut` `tr` `uniq` `sort` `column` `join` `paste` `comm` `diff` |\n| **Pipeline** | `tee` `xargs` |\n| **Data** | `jq` `yq` `xan` |\n| **System** | `ps` `env` `date` `hostname` `whoami` `which` `alias` `time` `sleep` |\n| **Output** | `echo` `printf` |\n| **Encoding** | `base64` `md5sum` `sha1sum` `sha256sum` `file` |\n| **Archive** | `gzip` `gunzip` `zcat` `tar` |\n| **Math** | `seq` `expr` |\n\nEvery command supports `--help` and tab completion for all flags.\n\n## PsBash vs Native PowerShell\n\n| Task | PsBash | Native PowerShell |\n|------|--------|-------------------|\n| List files | `ls -la` | `Get-ChildItem -Force \\| Format-List` |\n| Find by name | `find . -name '*.ps1'` | `Get-ChildItem -Recurse -Filter *.ps1` |\n| Top 5 CPU | `ps aux \\| sort -k3 -rn \\| head 5` | `Get-Process \\| Sort-Object CPU -Desc \\| Select -First 5` |\n| Count lines | `wc -l file.txt` | `(Get-Content file.txt).Count` |\n| Search files | `grep -r 'TODO' src/` | `Select-String -Path src/* -Pattern TODO -Recurse` |\n| JSON field | `cat f.json \\| jq '.name'` | `(Get-Content f.json \\| ConvertFrom-Json).name` |\n| Delete tree | `rm -rf dist/` | `Remove-Item dist/ -Recurse -Force` |\n| Disk usage | `du -sh * \\| sort -rh` | `Get-ChildItem \\| Sort Length -Desc \\| Select Name,Length` |\n\nBoth sides give you objects. PsBash just lets you type what you already know.\n\n## Testing\n\n```powershell\nInvoke-Pester ./tests/PsBash.Tests.ps1\n# 776 tests: 775 passing, 1 skipped (Windows-specific)\n```\n\nCI runs on Windows, Linux, and macOS via GitHub Actions.\n\n## Cross-Platform\n\n| Feature | Linux/macOS | Windows |\n|---------|-------------|---------|\n| File permissions | Real POSIX (`rwxr-xr-x`) | Approximated from ACLs |\n| `ps` backend | `/proc` filesystem | .NET `System.Diagnostics.Process` |\n| `ln -s` | Works normally | Requires Developer Mode |\n| `stat` | `/usr/bin/stat` | Pure .NET implementation |\n\n## Documentation\n\n**[standardbeagle.github.io/ps-bash](https://standardbeagle.github.io/ps-bash/)** -- full command reference, object type specs, pipeline cookbook, cross-platform guide.\n\n## License\n\nMIT\n\n## Contributing\n\nIssues and PRs welcome.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstandardbeagle%2Fps-bash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstandardbeagle%2Fps-bash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstandardbeagle%2Fps-bash/lists"}