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