Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell script to call git init in all subdirectories

I want to init repositories in all subdirectories in a given directory. Since there are about 200 of them (legacy projects), I want to automate it with PowerShell. So far I have:

 $items = Get-ChildItem -Path "."

    foreach ($item in $items)
    {
          if ($item.Attributes -eq "Directory")
          {
              $git = "C:\Program Files (x86)\Git\cmd\git"
              & $git "init"
          }
    }

Obviously I am missing a line where I make use of each subdirectory in the loop. In its current form, I believe all this does it call git init over and over in the same directory ("."), so what is the way to call git init from inside of each of the subdirectories? Is there a way to temporarily cd into each subdirectory found?

I tried something naïve like

& $item.Name + "\git init"

But it doesn't like that, for obvious reasons.

like image 969
starmandeluxe Avatar asked Oct 24 '25 02:10

starmandeluxe


2 Answers

The cmdlets you are looking for are Push-Location and Pop-Location. The former will change the current working directory to whatever argument you pass to it. The old location will be stored on a stack. Once you have changed the directory using Push-Location, you can execute commands locally as if you manually cd’d into them. Afterwards, call Pop-Location to clear the stack and go back to the original directory.

Btw. note that checking Attributes equality for "Directory" will not necessarily be good enough to identify directories. While you can be sure that you will only find directories using that, there may be other directories which have other attribute flags set as well. See also the FileAttributes enumeration.

A better way to check for directories is to check the PSIsContainer property. It will simply be true for directories, and otherwise false.

Using PowerShell’s piping, you can also write this all in a single line:

Get-ChildItem | ? { $_.PSIsContainer } | % { Push-Location $_.FullName; git init; Pop-Location }

This will first get all items in the current directory and push them into the pipe. Then they will be filtered for directories (? is filter), and then commands will be executed for each item that is left in the pipe (% is for each). So you call Push-Location to get to the directory’s location, call git init there, and then go back using Pop-Location.

Note: If you are using PowerShell 3, you can also use Get-ChildItem -Directory to filter for directories right away.

like image 117
poke Avatar answered Oct 25 '25 18:10

poke


All you have to do is call this command:

gci c:\parent\folder | ? { $_.PSIsContainer; } | % { cd $_.FullName; git init; };
  1. The first bit is an alias for Get-ChildItem, which gets a list of subdirectories and files of the "parent folder." It passes those items onto the next command via the pipe character |
  2. The PSIsContainer bit filters the list of "child items" for folders only, so as to exclude files. It passes these folders onto the next command via the pipe |
  3. The final bit is an alias for ForEach-Object, which performs a series of tasks for each object in the PowerShell pipeline.
    • Set the current location to the folder path
    • Call git init

Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!