DEV Community


Posted on • Updated on


Fosh: Execute shell commands in multiple directories grouped by tags

For developers who running the same command in different directories repeatedly, Fosh is a productivity tool that saves time by executing the command without having to change the directory. Unlike other similar tools, Fosh does not bound to a certain software (like Git for example), it can execute any shell command. It works at least on Windows and Linux.

If you prefer Bash, have a look at

  • Manage multiple Git repositors together
    • Checkout the same branch for project and its submodules
    • Commit with the same message: walk through the repos without interruption and copy / paste the same commit message
    • Prevent early push: you do not have to remember which repositories have modified, just look at them at the end of the day to see where you need to push
  • Control multiple vagrant machines at the same time

The essence of the code in a nutshell:

for(dir in selectedDirectories) {

This also means the name: for ... shell ... -> fosh.


$ npm install -g fosh

Get the source code, report bugs, open pull requests, or just star because you didn't know that you need it:


Tag: Assign tags to directories

The tags can be specified as command-line parameters prefixed with @, directories should be listed in the prompt, or piped to stdin.

$ fosh tag "@pictures" "@personal"
fosh: tag > /home/myself/photos
fosh: tag > /home/mom/my_little_family

$ echo -e "/home/myself/photos \n /home/mom/my_little_family" | fosh tag "@pictures" "@personal"

Find Git repositories

Tagging Git repositories under the current directory (./) with
"git-repos" tag:

# Linux / Windows Git Bash / ...
$ find "./" -name ".git" -printf "%h\n" | fosh tag "@git-repos"

# Windows PowerShell
$ Get-ChildItem './' -Recurse -Directory -Hidden -Filter '.git' | ForEach-Object { Split-Path $_.FullName -Parent } | fosh tag '@git-repos'

On Windows you can use Everything search engine's es command-line interface to find Git repositories rapidly. Use the following command in PowerShell for this (omit the path of the root directory (./src) to find everywhere):

$ es -regex '^\.git$' './src' | Split-Path -Parent | fosh tag '@git-repos'

List: Prints the path of the tag list file

You can edit it in a texteditor (Notepad, Vim, etc.).

Run: Execute commands in multiple directories

Arguments can be tags and paths.

$ fosh run "@git-repos" "../wip-project"
fosh: run > git status --short --branch

__ @1 awesome-project (/home/me/src/) ________________________________________
## master
 M package.json

__ @2 git-test (/home/me/src/) _______________________________________________
## master...origin/master
 M README.adoc
 M encoding/cp1250-encoding-dos-eol.txt
 M encoding/dos-eol.txt

__ @3 wip-project (/home/me/helping-tom/) ____________________________________
## master...origin/master
 M example-code.js

fosh: run > another command and so on ...

Filtering the directory list

If you want to execute a command only in certain directories, you can select them by their index.

fosh: run > @1,3 git status --short --branch

__ @1 awesome-project (/home/me/src/) ________________________________________
## master
 M package.json

__ @3 wip-project (/home/me/helping-tom/) ____________________________________
## master...origin/master
 M example-code.js

Execute in the most recently used directories

This is useful if the output is long and you want to execute additional commands on certain directories. In this case, open a new terminal window (so you can look back at results in the current terminal) and run the program without arguments: the directory list is always stored when tag or directory arguments are given, but if you run it without arguments, it executes the commands on the last specified directories.

$ fosh run "@git-repos" "../wip-project"
fosh: run > git status --short --branch

__ @1 awesome-project (/home/me/src/) ________________________________________
## master

# Another terminal

$ fosh run
fosh: WARNING: Using most recently used directory list
fosh: run > @3 git diff

__ @3 wip-project (/home/me/helping-tom/) ____________________________________
 example-code.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/example-code.js b/example-code.js
index 12b5e40..733220f 100644
--- a/example-code.js
+++ b/example-code.js

Top comments (0)

The AI Brief

AI generated git commit messages

Minimize the struggle of remembering what you just coded. AI-generated commits make it easier to manage projects and keep track of changes. The Nutlope/aicommits project demonstrates how AI can improve commit messages.

I open sourced an AI that creates any UI in seconds

Make AI-generated user interfaces a breeze. This open-source project harnesses the power of generative AI technologies like chatGPT to create versatile, quick, and intuitive UI components.

Use AI to commit like a PRO in 1 second

Upgrade your commit message game with AI. Boost your productivity by using ChatGPT to generate commit messages and avoid context switching. OpenCommit is an open-source library that helps you achieve this easily.

Build your own ChatGPT starter kit

Train AI models on custom data for improved domain-specific knowledge. Combine the power of WebView technologies and this starter kit to train your ChatGPT model on specific websites, allowing for better-optimized outcomes.