{"id":15669152,"url":"https://github.com/edjopato/project-below","last_synced_at":"2025-05-06T20:05:53.504Z","repository":{"id":39325667,"uuid":"454989611","full_name":"EdJoPaTo/project-below","owner":"EdJoPaTo","description":"Quickly find or run commands in many projects","archived":false,"fork":false,"pushed_at":"2025-04-23T22:10:41.000Z","size":110,"stargazers_count":3,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-23T23:23:35.106Z","etag":null,"topics":["cli","command-line","command-line-tool","dependency-manager","filesystem","git","npm","project-manager","rust","terminal","tool"],"latest_commit_sha":null,"homepage":"","language":"Rust","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/EdJoPaTo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2022-02-03T01:08:13.000Z","updated_at":"2025-04-03T22:41:30.000Z","dependencies_parsed_at":"2023-01-19T17:16:00.399Z","dependency_job_id":"c8cd327b-7d10-41d5-bc7c-aa3f0213d510","html_url":"https://github.com/EdJoPaTo/project-below","commit_stats":{"total_commits":108,"total_committers":2,"mean_commits":54.0,"dds":0.08333333333333337,"last_synced_commit":"845d5d16a9f35a5beda137b36ecdd208fcdc2c92"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdJoPaTo%2Fproject-below","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdJoPaTo%2Fproject-below/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdJoPaTo%2Fproject-below/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdJoPaTo%2Fproject-below/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EdJoPaTo","download_url":"https://codeload.github.com/EdJoPaTo/project-below/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252761140,"owners_count":21800124,"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":["cli","command-line","command-line-tool","dependency-manager","filesystem","git","npm","project-manager","rust","terminal","tool"],"created_at":"2024-10-03T14:21:41.214Z","updated_at":"2025-05-06T20:05:53.471Z","avatar_url":"https://github.com/EdJoPaTo.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Project below\n\n\u003e Quickly find or run commands in many projects\n\nAs I have many projects I often do the same tasks in multiple projects (like `git fetch`).\n\nDoing something like this is tedious:\n\n```bash\nls\ncd first\ngit fetch\ncd ..\ncd second\ngit fetch\ncd ..\n…\n```\n\nAnd can be done with this tool in a much simpler way:\n\n```bash\nproject-below --directory=.git git fetch\n\n# Or with an alias:\nalias gitBelow='project-below --directory=.git git'\ngitBelow fetch\n```\n\nFinding projects of a certain programming language below the current directory gets fairly easy this way:\n\n```bash\ncd ~\nproject-below --file=Cargo.toml\n```\n\nOutput:\n\n```plaintext\ngit/hub/EdJoPaTo/public/mqttui\ngit/hub/EdJoPaTo/public/project-below\ngit/hub/EdJoPaTo/public/website-stalker\n…\n```\n\n## Basic Idea\n\nThis tool is always used in the following way:\n\n```bash\nproject-below [OPTIONS] [COMMAND]...\n```\n\nWith the `OPTIONS` the sub-folders are filtered.\nThen in every matching folder the `COMMAND` is executed.\nCheck `--help` for the available filters.\n\nFor example lets run `git status` in every sub-folder which contains a `package.json` (probably some Node.js project):\n\n```bash\nproject-below --file=package.json git status\n```\n\nThis can be simplified with aliases like it is done in the [examples](#examples).\nThe first part (executable and options) always stays the same for this kind of query, only the command (or its arguments) changes.\nYou can put the first part in an alias and use the alias then:\n\n```bash\nalias npmBelow='project-below --file=package.json'\nnpmBelow git status\n```\n\n## Examples\n\n### [git](https://git-scm.com/)\n\nRun `git status` or `git fetch` in all git projects below the current directory:\n\n```bash\nalias gitBelow='project-below --directory=.git git'\ngitBelow status\ngitBelow status --short --branch\ngitBelow fetch\n```\n\n### [cargo](https://doc.rust-lang.org/cargo/)\n\n```bash\nalias cargoBelow='project-below --file=Cargo.toml cargo'\ncargoBelow check\ncargoBelow clean\n```\n\n### [Docker](https://www.docker.com/) / [Podman](https://podman.io/)\n\n```bash\nalias dockerBelow='project-below --file=Dockerfile docker'\ndockerBelow build .\n\nalias podmanBelow='project-below --file=Dockerfile podman'\npodmanBelow build .\n```\n\n### [dotnet](https://docs.microsoft.com/en-us/dotnet/core/tools/)\n\n```bash\nalias dotnetBelow='project-below --file=\"*.sln\" dotnet'\ndotnetBelow test\ndotnetBelow build\ndotnetBelow clean\n```\n\n### [NPM](https://www.npmjs.com/)\n\n```bash\nalias npmBelow='project-below --file=package.json npm'\nnpmBelow test\n\nalias npmBelow-clean='project-below --file=package.json --directory=node_modules rm -rf node_modules'\nnpmBelow-clean\n```\n\n### [PKGBUILD](https://wiki.archlinux.org/title/PKGBUILD)\n\n```bash\nalias makepkgBelow='project-below --file=PKGBUILD makepkg'\nmakepkgBelow -f\n```\n\n### [PlatformIO](https://platformio.org/)\n\n```bash\nalias pioBelow='project-below --file=platformio.ini pio'\npioBelow test\n\nalias pioBelow-clean='project-below --file=platformio.ini --directory=.pio rm -rf .pio'\npioBelow-clean\n```\n\n### [website-stalker](https://github.com/EdJoPaTo/website-stalker)\n\n```bash\nalias website-stalker-below='project-below --file=website-stalker.yaml website-stalker'\nwebsite-stalker-below run --all\n```\n\n### Add your own example\n\nFeel free to add your own example via Pull Request!\n\nPlease keep `git` and `cargo` as the first examples.\nAfter that all examples are alphabetically sorted.\n\n## Tips\n\n### Test everything\n\nTest your setup first without running a command and use without command or add `echo` instead.\nWhen building a command including for example `rm` it's wise to test it before running it.\n\n```diff\n-alias cargoBelow='project-below --file=Cargo.toml rm -rf target'\n+alias cargoBelow='project-below --file=Cargo.toml'\n```\n\n```diff\n-alias cargoBelow='project-below --file=Cargo.toml      rm -rf target'\n+alias cargoBelow='project-below --file=Cargo.toml echo rm -rf target'\n```\n\n### Smart `cd` change directory\n\nYou can create a smart `cd` command relatively easy with `project-below` and [`fzf`](https://github.com/junegunn/fzf).\nFor example switching into one of the git repositories can be done like this:\n\n```bash\nalias cdg='cd \"$(project-below --directory=.git | fzf)\"'\ncdg\n```\n\n### Use `sort`\n\nWhen using the listed output of found directories the result in unsorted due to multi-threading and the way the OS returns folders.\nUsing `sort` is neat here:\n\n```diff\n-alias cdg='cd \"$(project-below --directory=.git        | fzf)\"'\n+alias cdg='cd \"$(project-below --directory=.git | sort | fzf)\"'\n```\n\n### Use `nice`\n\nBuilds on a smaller machine with not as much computing power are annoying to run in the background.\n`nice` helps by allowing the OS to prioritize other processes instead. (Sound servers like `pipewire` are usually the opposite of nice to ensure no stutters in sound)\nYou can include it in your alias and all the commands will run via `nice`:\n\n```diff\n-alias cargoBelow='project-below --file=Cargo.toml      cargo'\n+alias cargoBelow='project-below --file=Cargo.toml nice cargo'\n```\n\nThis way processes will still take all the resources, but when multiple processes want them, the nicer one won't get as many. This is really neat for background or longer tasks that aren't time-critical.\n\nTip: `nice -n 19` is the nicest we can get. `nice` defaults to 10, so using `nice -n 19` in aliases results in being even nice to commands with just `nice`.\n\n### PAGER\n\nSome tools use a pager.\nFor example `git` uses `less` for some commands.\n`project-below` sets the environment variable `PAGER` to `cat` in order to work around this.\nIf you have set `GIT_PAGER` or another tool specific pager this will not help here.\nFor example include it into your alias:\n\n```diff\n-alias gitBelow='              project-below --directory=.git git'\n+alias gitBelow='GIT_PAGER=cat project-below --directory=.git git'\n```\n\n## How did I end up creating this project?\n\nFor some use cases this problem can be solved with `find` or [`fd`](https://github.com/sharkdp/fd), but gets annoying for some package managers.\n`gitBelow` for example can be realized like this:\n\n```bash\ngitBelow() {\n  find . -name \".git\" -type d -print -execdir git --no-pager $@ \\;\n}\n\ngitBelow fetch\n```\n\nSadly this approach lacks auto-completion of `git` commands: `gitBelow stat\u003cTab\u003e` does not auto-complete to `gitBelow status`.\nBut this is only an annoyance.\n\nFor commands like `npm` it's not even simple to come up with a useful solution.\n`find` does not use ignore files and ends up with all the `package.json` files in the `node_modules` folder (which is often a lot).\n`fd` on the other hand uses ignore files but `--exec` is always executed from the working directory from where the command was started.\n`git` for example has `-C` to use another path, but tools like `npm` do not.\nThis requires some workarounds like spawning a `bash` with a `cd` command at first.\nIt works but there won't be auto-completion of commands either.\nAlso, it creates a lot of bash / alias dark magic my future me wants to understand.\nIt is also way harder to adapt to new use cases or other dependency managers.\n\nIn turn, I created this tool which helps me to do exactly what I need in a simple way.\n\nAs this tool uses the same directory walker like [`fd`](https://github.com/sharkdp/fd) or [`rg`](https://github.com/BurntSushi/ripgrep) it's way faster than `find` can ever be and uses smart features like ignore files, it skips hidden folders and so on.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedjopato%2Fproject-below","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedjopato%2Fproject-below","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedjopato%2Fproject-below/lists"}