Written by Anonymous


# =========================
# 0. SETUP
# =========================
$cartella = (Get-Location)

# =========================
# 1. BACKUP AUTOMATICO
# =========================
$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$backup_dir = Join-Path $cartella "backup_rinomina_$timestamp"

New-Item -Path $backup_dir -ItemType Directory -Force | Out-Null

Get-ChildItem -Path $cartella -File | ForEach-Object {
    # non copiare i backup precedenti per evitare accumulo
    if ($_.Name.StartsWith("backup_rinomina_")) { return }

    Copy-Item -Path $_.FullName -Destination (Join-Path $backup_dir $_.Name) -Force
}

Write-Host "`nBackup creato in: $backup_dir`n"

# =========================
# 2. COSTRUZIONE LISTA RINOMINE
# =========================
$rinoMine = New-Object System.Collections.Generic.List[object]
$destinazioni = New-Object System.Collections.Generic.HashSet[string]

# regex: ^(\d+)(.*)$
$pattern = '^(?<numero>\d+)(?<resto>.*)$'

Get-ChildItem -Path $cartella -File | ForEach-Object {
    # evita lo script stesso
    if ($_.Name -eq "rinomina.py") { return }

    $nome = $_.BaseName   # stem
    $estensione = $_.Extension

    $m = [regex]::Match($nome, $pattern)
    if (-not $m.Success) { return }

    $numero = $m.Groups["numero"].Value
    $resto  = $m.Groups["resto"].Value

    # NON toccare file già a 3 cifre o più (100-999 ecc.)
    if ($numero.Length -ge 3) { return }

    $nuovo_numero = "{0:D3}" -f [int]$numero
    $nuovo_nome = $nuovo_numero + $resto + $estensione

    # controllo conflitti
    if ($destinazioni.Contains($nuovo_nome)) {
        Write-Host "CONFLITTO: più file vogliono diventare $nuovo_nome"
        return
    }

    $destinazioni.Add($nuovo_nome) | Out-Null
    $rinoMine.Add(@($_, $nuovo_nome))  # (file, nuovo_nome)
}

# =========================
# 3. CONTROLLO PRELIMINARE
# =========================
if ($rinoMine.Count -eq 0) {
    Write-Host "Nessun file da rinominare."
    Read-Host "Premi INVIO per uscire..."
    exit
}

Write-Host "`nANTEPRIMA RINOMINE:`n"

# ordinamento per nome file originale
$rinoMine |
    Sort-Object { $_[0].Name } |
    ForEach-Object {
        $file = $_[0]
        $nuovo = $_[1]
        Write-Host "$($file.Name)  ->  $nuovo"
    }

$risposta = (Read-Host "`nProcedere con la rinomina? (S/N): ").Trim().ToUpper()

if ($risposta -ne "S") {
    Write-Host "Operazione annullata."
    Read-Host "Premi INVIO per uscire..."
    exit
}

# =========================
# 4. RINOMINA SICURA A DUE PASSI
# =========================
$temp_map = New-Object System.Collections.Generic.List[object]

# PASSO 1: nomi temporanei (evita collisioni)
for ($i = 0; $i -lt $rinoMine.Count; $i++) {
    $file = $rinoMine[$i][0]
    $nuovo_nome = $rinoMine[$i][1]

    $temp_name = "__temp__$i__$($file.Name)"
    $temp_full = Join-Path $cartella $temp_name
    $file_full = $file.FullName

    Rename-Item -Path $file_full -NewName $temp_name
    $temp_map.Add(@($temp_name, $nuovo_nome))
}

# PASSO 2: nomi finali
foreach ($pair in $temp_map) {
    $temp_name = $pair[0]
    $nuovo_nome = $pair[1]

    Rename-Item -Path (Join-Path $cartella $temp_name) -NewName $nuovo_nome
}

Write-Host "`nRinomina completata con successo."
Read-Host "Premi INVIO per uscire..."
Notepad
Select All