Hromadná normalizace názvů souborů a adresářů pomocí powershelu

 

 

Potřeboval jsem provést normalizaci jmen souborů a adresářů, tak, abych je případně mohl použít pro webový přístup.  Skript není úplně optimalizovaný a chybí v něm ošetření neúspěšných přejmenování.
pozn: zase mě v powershelu dostalo volání a vracení hodnot funkce
funkce voláme: Jmeno_funce Parametr1 Parametr2 a nikoli
Jmeno_funce(Parametr1, Parametr2).
V druhém případě se poweshell snaží vyhodnotit výraz v závorce, který vloží jako jediný parametr.
Dále pokud pro testovací účely použiju příkaz echo místo funkce [System.Console]::WriteLine, pak se výstup z echa dostává do vrácené hodnoty.
Zkuste si pohrát s:

function pokus1 {
echo „AB“;
return „CD“;
}

function pokus2 {
echo „EF“;
return pokus1;
}

$A=pokus2 ;
echo $A;
echo „—„;
echo („Vysledek=“ + $A);
echo $(„Vysledek=“ + $A);

Docela zmatečné výsledky

Tady je vlastní zdroják:

# NormalizeDIRs

$ROOTdir=“V:\Zaznamy_ze_skoleni“;
# pole kam se budou ukládat plné jména přejmenovaných adresářů. Pokud tam není nalezena shoda, tak adresář přejmenuj
$script:APrejmenovano=@();

# Pokud je v poli APrejmenovano již uloženo plné jméno adresáře, není už třeba přejmenovávat
# v podstatě je to funkce navíc…
function NeedRename {
param ($CeleJmeno)

# [System.Console]::WriteLine(„NeedRename: “ + $CeleJmeno);
foreach ($B in $script:APrejmenovano){
     if ($B.FullName -eq $CeleJmeno) { return „NE“; }
   }
   return „ANO“;
}
#———————-

# odstraní diakritiku
function RemoveDiacritics {
param ($s)

#[System.Console]::WriteLine(„RemoveDiacritics=“ + $s);
$s = $s.Normalize([System.Text.NormalizationForm]::FormD);
   $sb = „“;
   for ($i = 0; $i -lt $s.Length; $i++) {
     if ([System.Globalization.CharUnicodeInfo]::GetUnicodeCategory($s[$i]) -ne [System.Globalization.UnicodeCategory]::NonSpacingMark) {
       $sb += $s[$i] ;
     }
   }
   return $sb;
}
#———————-

# tady se snažím pomocí záměn trochu učesat tvar. Zvláště takové zběsilosti jako je tečka mezera tečka před příponou (jmeno. .txt).
# Dalo by se tu vymyslet něco moudřejšího.
function NormalizujJmeno {
param ($Ret);

# [System.Console]::WriteLine(„Normalizuji: „+$Ret);
$vyst = (RemoveDiacritics $Ret);
$vyst = $vyst -replace „[=\s]“, „_“;
$vyst = $vyst -replace „[+;,\(\)]“, „-„;
#$vyst = $vyst -replace „\._“, „.“;
$vyst = $vyst -replace „_\.“, „.“;
$vyst = $vyst -replace „-_“, „-„;
$vyst = $vyst -replace „_-„, „-„;
$vyst = $vyst -replace „_+“, „_“;
$vyst = $vyst -replace „-+“, „-„;
$vyst = $vyst -replace „\.+“, „.“;
$vyst = $vyst -replace „\.-„, „-„;
$vyst = $vyst -replace „\.-„, „-„;

return $vyst ;
}
#———————-

# Tady je vlastní přejmenování adresáře. Pokud po normalizaci názvu dojde ke kolizi jmen, přidám na konec -00n „-{0:D3}“
function jbRenameDIR {
param ($Jmeno,$Rodic)

$Rozliseni=“;
   $i=0;
   $NoveJmeno = NormalizujJmeno $Jmeno;
   $OldFullName = $Rodic+’\’+$Jmeno;
   $NewFullName = $Rodic+’\’+$NoveJmeno+$Rozliseni ;
# pokud jsme narazili na adresář, kde se po normalizaci normalizaci nic nemění, nesnažíme se o rename-item – padá to na chybu
if ($OldFullName -ne $NewFullName) {
# pokud uz nazev existuje , dam priponu -ddd napr -001)
while (Test-Path $NewFullName) {
       $i++;
       $Rozliseni = „-{0:D3}“ -f $i;
       $NewFullName = $Rodic+’\’+$NoveJmeno+$Rozliseni;
     }
    $NoveJmeno = $NoveJmeno+$Rozliseni ;
# [System.Console]::WriteLine(„Rename : “ +$OldFullName +“ -> „+$NoveJmeno);
rename-item „$OldFullName“ „$NoveJmeno“ -force ;
   }
# tady ukládám do porovnávacího pole nové plné jméno
   $script:APrejmenovano += $NewFullName;
   return $script:APrejmenovano[-1] ;
}
#———————-

# Prejmenovani Souboru. Tady v případě kolize jmen dam rozlišovaci řetězec -00n před příponu
function jbRenameFile {
param ($Jmeno,$Rodic)

$Rozliseni=“;
   $i=0;

if ($Jmeno -match „(.*)\.(.*)“) {
     $Basename=$matches.1;
     $extension=‘.’+$matches.2;
   } else {
     $Basename=$Jmeno;
     $extension=“;
   }
   $NoveJmeno = NormalizujJmeno $BaseName;
   $OldFullName = $Rodic+’\’+$Jmeno;
$NewFullName = $Rodic+’\’+$NoveJmeno+$Rozliseni+$extension ;
if ($OldFullName -ne $NewFullName) {
# pokud uz nazev existuje , dam priponu -ddd napr -001)
while (Test-Path $NewFullName) {
       $i++; $Rozliseni = „-{0:D3}“ -f $i;
       $NewFullName = $Rodic+’\’+$NoveJmeno+$Rozliseni+$extension;
      }
   $NoveJmeno = $NoveJmeno+$Rozliseni+$extension ;
# [System.Console]::WriteLine(„Rename : “ +$OldFullName +“ -> „+$NoveJmeno);
  rename-item „$OldFullName“ „$NoveJmeno“ -force ;
 }
return $NewFullName; ;
}
#———————-

function jbRenameDIRs {
param ($D)

$AD=Get-ChildItem -Path $D |where Attributes -eq Directory
   if ($AD.count -gt 0) {
     foreach ($pol in $AD) {
       $Rename = NeedRename $pol.Fullname ;
       If ($Rename -eq „ANO“) {
         $NJ = jbRenameDIR $pol.Name $pol.Parent.FullName ;
# [System.Console]::WriteLine( „Prejmenovano na „+ $NJ );
# rady je rekurzivní volání, ale s novým jmenem NJ
        jbRenameDIRs $NJ ;
       } else {
         echo „Sem nikdy nepujdu“;
         jbRenameDIRs $pol.FullName ;
       }
     }
   }
}
#———————-

function jbRenameFiles {
param ($D)

# tady volám Get-ChildItem zjednodušeně se switchem -recurse
   $AD=Get-ChildItem -Path $D -recurse|where Attributes -ne Directory
   if ($AD.count -gt 0) {
     foreach ($pol in $AD){
       $parent=split-path $pol.VersionInfo.FileName ;
       $NJ = jbRenameFile $pol.Name $parent ;
# [System.Console]::WriteLine( „Prejmenovano na „+ $NJ );
     }
   }
}
#—————–

# nejprve přejmenuji adresářovou strukturu
jbRenameDIRs($ROOTdir);
# a teď soubory
jbRenameFiles($ROOTdir);

Ještě pokud chceme, aby se okno powershellu zavřelo po dokončení akce
if ($Host.Name -eq ‚ConsoleHost‘) {Stop-Process $PID}

Skript volám v plánovači úloh powershell s parametrem

-command „& {. ‚c:\PSS\NormalizeDir.ps1‘}“

Snad tím někomu udělám radost

 

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *