{"id":20830011,"url":"https://github.com/bimlas/bash-mosh","last_synced_at":"2026-03-06T12:32:52.837Z","repository":{"id":81034475,"uuid":"189668314","full_name":"bimlas/bash-mosh","owner":"bimlas","description":"Bash: Run shell commands in multiple directories grouped by tags","archived":false,"fork":false,"pushed_at":"2024-02-05T19:46:44.000Z","size":24,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-07T22:11:31.192Z","etag":null,"topics":["bash","cli","command-line","git","shell","terminal"],"latest_commit_sha":null,"homepage":"","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/bimlas.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":"2019-05-31T23:08:54.000Z","updated_at":"2024-02-05T19:54:06.000Z","dependencies_parsed_at":null,"dependency_job_id":"bb3a1877-916c-4871-85b1-d461d3c981c9","html_url":"https://github.com/bimlas/bash-mosh","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/bimlas/bash-mosh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bimlas%2Fbash-mosh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bimlas%2Fbash-mosh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bimlas%2Fbash-mosh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bimlas%2Fbash-mosh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bimlas","download_url":"https://codeload.github.com/bimlas/bash-mosh/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bimlas%2Fbash-mosh/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30176258,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T11:48:51.886Z","status":"ssl_error","status_checked_at":"2026-03-06T11:48:51.460Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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","command-line","git","shell","terminal"],"created_at":"2024-11-17T23:22:54.676Z","updated_at":"2026-03-06T12:32:52.820Z","avatar_url":"https://github.com/bimlas.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mosh: Run shell commands in multiple directories grouped by tags\n\nFor developers who **running the same command in different directories**\nrepeatedly, Mosh is a productivity tool that saves time by **executing the\ncommand without having to change the directory**. Unlike other similar tools,\nMosh does not bound to a certain software (like Git for example), it can\n**execute any shell command**. **It works on any Bash-compitable shell**\n(Bash, Zsh, Git Bash on Windows, etc.).\n\n![screencast](https://i.imgur.com/OFKXZMR.gif)\n\n- **Manage multiple Git repositors together**\n  - `push` and `pull` all of your repos at once\n  - Checkout the same branch for project and its submodules\n  - Commit with the same message: walk through the repos without\n    interruption and copy / paste the same commit message\n  - Prevent early push: you do not have to remember which repositories have\n    modified, just look at them at the end of the day to see where you need to\n    push\n- **Control multiple vagrant machines at the same time**\n\nThe essence of the logic in a nutshell:\n\n```\nfor dir in $selected_directories; do\n  cd $dir\n  $shell_command\ndone\n```\n\n## Installation\n\nDownload the `bin/mosh` script and place it somewhere on your PATH or use\n[Basher](https://github.com/basherpm/basher).\n\nGet the source code, report bugs, open pull requests, or just star because\nyou didn't know that you need it:\n\n- https://github.com/bimlas/bash-mosh (please star if you like it)\n\n## Usage\n\n## Run: Execute commands in multiple directories\n\nLet's say that you have a bunch of directories that start with the same prefix\n(`g`) in `/usr/share`. **You want to issue the same commands to all of them**.\nYou can use `mosh run` with a wild card for the directory names you want to\ninteract with:\n\n```\n$ mosh run /usr/share/g*\n```\n\nThis will open up an interactive terminal where you can run one or more\ncommands. For example list the content of them:\n\n```\nmosh \u003e ls\n\n______________________________________________________________________________\n@1 gdb (/usr/share)\n\nauto-load\n\n______________________________________________________________________________\n@2 git (/usr/share)\n\nmsys2-32.ico  ReleaseNotes.css\n\n______________________________________________________________________________\n@3 glib-2.0 (/usr/share)\n\ngdb  schemas\n\n...\n```\n\nExiting from the program is done with Control+D.\n\nOf course, this could have been done with the `ls /usr/share/g*` command.\n**The real targets of the program are the commands that can only be executed\nin the current directory, so we should enter the directory before issuing the\ncommand.** As a useful example, we can check the status for a bunch of Git\nrepos.\n\n```\n$ mosh run ~/src/* \"../wip-project\"\nmosh \u003e git status --short --branch\n\n______________________________________________________________________________\n@1 awesome-project (/home/me/src/)\n\n## master\nAM README.md\n M package.json\n\n______________________________________________________________________________\n@2 git-test (/home/me/src/)\n\n## master...origin/master\n M README.adoc\n M encoding/cp1250-encoding-dos-eol.txt\n M encoding/dos-eol.txt\n\n______________________________________________________________________________\n@3 wip-project (/home/me/helping-tom/)\n\n## master...origin/master\n M example-code.js\n\n==============================================================================\nmosh \u003e another command and so on ...\n```\n\n**Arguments can be tags and paths** (see below for the description of tags).\n\n```\n$ mosh run \"@git-repos\" \"../wip-project\"\n```\n\nSince you will mostly use the `run` command, you may want to **assign an\nalias** to execute the command with less typing.\n\n```\n# Before\n$ mosh run ~/src/* \"../wip-project\"\n\nalias run=\"mosh run\"\n\n# After\n$ run ~/src/* \"../wip-project\"\n```\n\n### Filtering the directory list\n\nIf you want to **execute a command only in certain directories**, you can\nselect them by their index.\n\n```\nmosh \u003e @1,3 git status --short --branch\n\n______________________________________________________________________________\n@1 awesome-project (/home/me/src/)\n\n## master\nAM README.md\n M package.json\n\n______________________________________________________________________________\n@3 wip-project (/home/me/helping-tom/)\n\n## master...origin/master\n M example-code.js\n```\n\n### Execute in the most recently used directories\n\n**This is useful if the output is long** and you want to execute additional\ncommands on certain directories. In this case, open a new terminal window (so\nyou can look back at results in the current terminal) and run the program\nwithout arguments: the directory list is always stored when tag or directory\narguments are given, but if you run it without arguments, it executes the\ncommands on the last specified directories.\n\n```\n$ mosh run \"@git-repos\" \"../wip-project\"\nmosh \u003e git status --short --branch\n\n______________________________________________________________________________\n@1 awesome-project (/home/me/src/)\n\n## master\nAM README.md\n...\n\n# Another terminal\n\n$ mosh run\nmosh ! WARNING: Using most recently used directory list\nmosh \u003e @3 git diff\n\n______________________________________________________________________________\n@3 wip-project (/home/me/helping-tom/)\n\n example-code.js | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/example-code.js b/example-code.js\nindex 12b5e40..733220f 100644\n--- a/example-code.js\n+++ b/example-code.js\n...\n```\n\n### Execute non-interactively\n\nIf you want to use it within a script or in scheduled tasks, you can also send\ncommands to stdin.\n\n```\n$ echo \"cp -r ./ ~/image_backups\" | mosh run \"@pictures\" \u003e /dev/null\n```\n\n### Check the exit code of the previous command\n\nIf a command requires the success of the same command in the previous\ndirectory, you can check the exit code.\n\n```\nmosh \u003e if [[ $? == 0 ]]; then echo \"Running\"; non_existent_command; else echo \"Not running\"; fi\n______________________________________________________________________________\n@1 awesome-project (/home/me/src/)\n\nRunning\n/bin/bash: non_existent_command: command not found\n\n______________________________________________________________________________\n@2 git-test (/home/me/src/)\n\nNot running\n\n______________________________________________________________________________\n@3 wip-project (/home/me/helping-tom/)\n\nNot running\n```\n\n## Tag: Assign tags to directories\n\nTo avoid having to always type the path of directories, you can assign them to\ntags (think of them as bookmarks).\n\nThe tags can be specified as command-line parameters prefixed with `@`,\ndirectories should be listed in the prompt, or piped to stdin.\n\n```\n$ mosh tag \"@pictures\" \"@personal\"\n/home/myself/photos\n/home/mom/my_little_family\n../granny\n\n$ echo \"./\" | mosh tag \"@pictures\" \"@personal\"\n```\n\nTag files are stored in `~/.mosh` directory, you can edit them with any text\neditor.\n\n### Find Git repositories\n\n**Tagging Git repositories** under the current directory (`./`) with\n\"git-repos\" tag:\n\n```\n$ find \"./\" -name \".git\" -printf \"%h\\n\" | mosh tag \"@git-repos\"\n```\n\n### Tag new repositories automatically\n\nIn order not to miss any newly created or cloned repositories, one of the [Git\nhooks](https://git-scm.com/docs/githooks)\n([post-commit](https://git-scm.com/docs/githooks#_post_commit) or\n[pre-push](https://git-scm.com/docs/githooks#_pre_push) for example) can be\nused to automatically assign the repository path to a default tag.\n\n```\n#!/bin/sh\nif ( which mosh \u0026\u003e /dev/null ); then\n  echo \".\" | mosh tag \"@git\" \u0026\u003e /dev/null \u0026\nfi\n```\n\n## FAQ\n\n### I use MinTTY on Windows and XY don't work or work differently\n\nUnder [MinTTY](https://mintty.github.io/) (default terminal emulator of Git\nfor Windows), it is not possible to identify exactly that `stdin` is a\nterminal or pipe (see https://duckduckgo.com/?q=MinTTY+is+not+a+TTY), so\nsome things may work differently than in other terminals. Try using another\nterminal like system default, your IDE's builtin terminal,\n[Conemu](https://conemu.github.io/),\n[Alacritty](https://github.com/jwilm/alacritty).\n\n## Similar projects\n\n- https://github.com/joowani/dtags\n- https://github.com/coderaiser/node-longrun\n- https://github.com/MamadouSy/fed\n- https://github.com/isacikgoz/gitbatch\n- http://myrepos.branchable.com/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbimlas%2Fbash-mosh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbimlas%2Fbash-mosh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbimlas%2Fbash-mosh/lists"}