SUPERCAT.DEV

Benvenut* sul mio blog

WIN

Unione file in uno unico

11-08-2026

Compatta in un unico file di testo il codice

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

# Cartella di lavoro: la cartella in cui si trova questo script.
# Se eseguito in modo interattivo, usa la cartella corrente.
$Root = if ([string]::IsNullOrWhiteSpace($PSScriptRoot)) {
    (Get-Location).Path
} else {
    $PSScriptRoot
}

$OutputFileName = 'Export-llm.md'
$OutputPath = Join-Path $Root $OutputFileName

# Estensioni da esportare.
# Le chiavi sono in minuscolo perché il confronto viene normalizzato.
$LanguageByExtension = @{
    '.cs'     = 'csharp'
    '.vb'     = 'vbnet'
    '.php'    = 'php'
    '.twig'   = 'twig'
    '.yaml'   = 'yaml'
    '.yml'    = 'yaml'
    '.json'   = 'json'
    '.vbproj' = 'xml'
    '.csproj' = 'xml'
    '.config' = 'xml'
}

$Utf8NoBom = New-Object System.Text.UTF8Encoding($false)

function Get-RelativeProjectPath {
    param(
        [Parameter(Mandatory = $true)] [string]$BasePath,
        [Parameter(Mandatory = $true)] [string]$FullPath
    )

    $resolvedBase = (Resolve-Path -LiteralPath $BasePath).Path
    $resolvedFull = (Resolve-Path -LiteralPath $FullPath).Path

    if (-not $resolvedBase.EndsWith([System.IO.Path]::DirectorySeparatorChar)) {
        $resolvedBase += [System.IO.Path]::DirectorySeparatorChar
    }

    $baseUri = New-Object System.Uri($resolvedBase)
    $fileUri = New-Object System.Uri($resolvedFull)

    return [System.Uri]::UnescapeDataString(
        $baseUri.MakeRelativeUri($fileUri).ToString()
    )
}

function Get-MarkdownFence {
    param(
        [Parameter(Mandatory = $true)] [AllowEmptyString()] [string]$Content
    )

    $maxBacktickRun = 0
    $matches = [regex]::Matches($Content, '`+')

    foreach ($match in $matches) {
        if ($match.Value.Length -gt $maxBacktickRun) {
            $maxBacktickRun = $match.Value.Length
        }
    }

    $fenceLength = [Math]::Max(3, $maxBacktickRun + 1)
    return ('`' * $fenceLength)
}

function Write-TextFile {
    param(
        [Parameter(Mandatory = $true)] [string]$Path,
        [Parameter(Mandatory = $true)] [AllowEmptyString()] [string]$Content
    )

    [System.IO.File]::WriteAllText($Path, $Content, $Utf8NoBom)
}

function Append-TextFile {
    param(
        [Parameter(Mandatory = $true)] [string]$Path,
        [Parameter(Mandatory = $true)] [AllowEmptyString()] [string]$Content
    )

    [System.IO.File]::AppendAllText($Path, $Content, $Utf8NoBom)
}

$Root = (Resolve-Path -LiteralPath $Root).Path

$extensions = @($LanguageByExtension.Keys)

$files = @(
    Get-ChildItem -LiteralPath $Root -Recurse -File |
        Where-Object {
            $extension = $_.Extension.ToLowerInvariant()
            $extensions -contains $extension
        } |
        Sort-Object FullName
)

$generatedAt = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
$extensionList = ($extensions | Sort-Object | ForEach-Object { '`' + $_ + '`' }) -join ', '

$header = @"
# LLM Project Export

Generato: $generatedAt  
Radice: `$Root`  
Estensioni incluse: $extensionList  
File trovati: $($files.Count)

"@

Write-TextFile -Path $OutputPath -Content $header

if ($files.Count -eq 0) {
    Append-TextFile -Path $OutputPath -Content "Nessun file trovato.$([Environment]::NewLine)"
    Write-Host "OK   ${OutputFileName}: 0 file"
    exit 0
}

foreach ($file in $files) {
    $relativePath = Get-RelativeProjectPath -BasePath $Root -FullPath $file.FullName
    $extension = $file.Extension.ToLowerInvariant()
    $language = $LanguageByExtension[$extension]
    $content = [System.IO.File]::ReadAllText($file.FullName)
    $fence = Get-MarkdownFence -Content $content

    $block = @"
## $relativePath

$fence$language
$content
$fence

"@

    Append-TextFile -Path $OutputPath -Content $block
}

Write-Host "OK   ${OutputFileName}: $($files.Count) file"
Write-Host "Creato: $OutputPath"

Per evitare errore

.\Export.ps1: File C:\xxx\Export.ps1 cannot be loaded. The file C:\xxx\Export.ps1 is not digitally signed. You cannot run this script on the current system. For more information about running scripts and setting execution policy, see about_Execution_Policies at https://go.microsoft.com/fwlink/?LinkID=135170.

Lanciare lo script così:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File "Export.ps1"