Public/Get-SingleFolderFromGitRemote.ps1
|
<#
.SYNOPSIS Downloads all files from a specific folder in a GitHub public repository on selected branch .DESCRIPTION Queries the GitHub Trees API for the specified repository and branch, filters files under the target folder, and downloads each file into a local output directory. Only files (blob entries) are downloaded. .PARAMETER Branch Branch name to read from in the target repository. Default: main Alias: b .PARAMETER Folder Repository folder path to download files from (for example: src/utils). Alias: f .PARAMETER Repo GitHub repository in owner/name format (for example: octocat/Hello-World). Alias: r .PARAMETER OutputDir Local folder to save downloaded files into. If omitted or empty, defaults to ./downloaded-folder. When an empty value is explicitly passed, the script derives the folder name from the leaf of -Folder. Alias: o .EXAMPLE Get-SingleFolderFromGitRemote -Repo "octocat/Hello-World" -Folder "docs" Downloads all files under docs/ from the main branch to ./downloaded-folder. .EXAMPLE Get-SingleFolderFromGitRemote -r "microsoft/PowerShell" -f "tools/packaging" -b "master" -o "./pkg" Downloads files under tools/packaging/ from the master branch into ./pkg. .NOTES Requires internet access and permission to read the target repository. For private repositories, this script would need authentication headers. #> function Get-SingleFolderFromGitRemote { param( [Parameter(Mandatory = $false)] [Alias('b')] [string]$Branch = 'main', [Parameter(Mandatory = $true, Position = 0)] [Alias('f')] [string]$Folder, [Parameter(Mandatory = $true, Position = 1)] [Alias('r')] [string]$Repo, [Parameter(Mandatory = $false)] [Alias('o')] [string]$OutputDir = './downloaded-folder' ) if ([string]::IsNullOrWhiteSpace($OutputDir)) { $leaf = Split-Path -Path $Folder -Leaf if ([string]::IsNullOrWhiteSpace($leaf)) { $leaf = 'downloaded-folder' } $OutputDir = "./$leaf" } New-Item -ItemType Directory -Path $OutputDir -Force Write-Host "Downloading folder '$Folder' from $Repo (branch: $Branch)" Write-Host "Saving to: $OutputDir" Write-Host "" $apiUrl = "https://api.github.com/repos/${Repo}/git/trees/${Branch}?recursive=1" try { $response = Invoke-RestMethod -Uri $apiUrl -Headers @{ Accept = 'application/vnd.github.v3+json' } } catch { throw "Failed to fetch file list from GitHub API: $($_.Exception.Message)" } $prefix = "$Folder/" $files = @($response.tree | Where-Object { $_.path -like "$prefix*" -and $_.type -eq 'blob' } | Select-Object -ExpandProperty path) if ($files.Count -eq 0) { throw "No files found under '$Folder' in $Repo on branch '$Branch'." } foreach ($filePath in $files) { $fileName = Split-Path -Path $filePath -Leaf $destination = Join-Path -Path $OutputDir -ChildPath $fileName $rawUrl = "https://raw.githubusercontent.com/$Repo/$Branch/$filePath" Write-Host "Downloading: $filePath -> $destination" try { Invoke-WebRequest -Uri $rawUrl -OutFile $destination -UseBasicParsing | Out-Null } catch { throw "Failed to download ${filePath}: $($_.Exception.Message)" } } Write-Host "" Write-Host "Folder downloaded to $OutputDir" } |