单盘迁移
One Drive Migration
我正在尝试将文件服务器迁移到 One Drive 问题是有很多文件夹和文件带有特殊字符,例如“|” , '<' 等..
而且出于某种原因,该公司使用“*”进行版本控制,例如:
'*' => v.1
'**' => v.2
等...
所以我写了一个 Powershell 脚本来重命名所有包含特殊字符的文件和文件夹。
#Files
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace(":","-")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("<","-")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace(">","-")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("?","-")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("/","-")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("|","-")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("**********","10")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*********","9")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("********","8")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*******","7")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("******","6")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*****","5")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("****","4")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("***","3")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("**","2")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*","1")}
#Directories
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace(":","-")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("<","-")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace(">","-")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("?","-")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("/","-")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("|","-")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("**********","10")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*********","9")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("********","8")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*******","7")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("******","6")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*****","5")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("****","4")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("***","3")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("**","2")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*","1")}
所以这工作正常,但由于某种原因,我在重命名文件夹时遇到很多错误,即使它工作正常...
错误:
… curse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*", …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Source and destination path must be different.
我也试过这个帖子 suggest 但这对我不起作用:
有人知道我为什么会收到此错误吗?以及如何修复它?
提前致谢。
这个错误是正常的,如果你没有理由重命名目录或文件,因为文件名是可以的,没有字符可以修改,名称保持不变,所以会显示一个错误,说你不能重命名一个file/directory同名。
尽管出现此错误,但过程并未停止,对最终结果没有影响
我建议您将所有键设置为搜索,对象中的新值:
#add your template to replace
$r = @{
":" = "-"
"<" = "-"
"**********" = "10";
"*********" = "9";
"********" = "8"
}
$Folders=Get-ChildItem -Directory -path -Recurse
foreach($folder in $Folders){
$newname = $folder.Name
foreach($k in $r.Keys){
$newname = $newname.Replace($k,$r.$k)
}
#rename only if original name and newname are differents
if(!$newname.equals($folder.Name)){
Rename-Item -Path $folder.FullName -NewName $newname
}
}
对你的文件做同样的事情......
您 运行 10 行代码每行仅重命名一种匹配类型,但实际上您 运行 相同的循环 10 次,在这种情况下,您的代码尝试重命名所有文件夹时间,但是当它尝试重命名具有相同 newName
的文件夹时出错,因为 Rename-Item
尝试重命名它,即使新名称与旧名称相同,它似乎没有一个验证器。
在这种情况下,“最便宜”的解决方案是添加 -ErrorAction SilentlyContinue
。但更复杂的解决方案是使用 if
语句或更适合案例 switch
.
的语句来验证您的数据集
更新:Regex
可能不是最容易处理的事情,因此下面的示例也说明了通配符 *
字符。
$allFolders=Get-ChildItem -Directory -Recurse
foreach($folder in $allFolders){
switch -Regex ($folder.Name){
'[:<>?\|]'{
$newName=$folder.Name.replace("[:<>?\|]","-")
Rename-Item -Path $folder.FullName -NewName $newName
}
'\*'{
$regexFormat = '\*'
$matchNumber=[regex]::Matches($folder.Name, $regexFormat) | ForEach-Object { $_.value }
$newName=$folder.Name.replace("*",$matchNumber.Count)
Rename-Item -Path $folder.FullName -NewName $newName
}
}
}
这样,您将 运行 1 次循环而不是 10 次循环,并且您只尝试重命名与您提供的模式相匹配的项目,因此与您使用的多行代码相比,您将看到显着的性能提升.
在我的 Windows 机器上,我不能在文件或文件夹名称中使用这样的字符,但理论上这应该可行:
(Get-ChildItem -File) | ForEach-Object {
$_ | Rename-Item -NewName {
# replace the '*' by the number of consecutive asterikses found
$name = $_.Name
$match = ([regex] '(\*+)').Match($name)
while ($match.Success) {
$name = $name -replace [regex]::Escape($match), $match.Length
$match = $match.NextMatch()
}
# finally replace the other special characters by a hyphen
$name -replace '[:<>?/|]', '-'
}
}
Get-ChildItem 周围的括号强制它在管道重命名之前完成收集。否则,您最终可能会尝试重命名已处理的项目
我正在尝试将文件服务器迁移到 One Drive 问题是有很多文件夹和文件带有特殊字符,例如“|” , '<' 等..
而且出于某种原因,该公司使用“*”进行版本控制,例如:
'*' => v.1
'**' => v.2
等...
所以我写了一个 Powershell 脚本来重命名所有包含特殊字符的文件和文件夹。
#Files
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace(":","-")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("<","-")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace(">","-")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("?","-")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("/","-")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("|","-")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("**********","10")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*********","9")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("********","8")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*******","7")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("******","6")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*****","5")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("****","4")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("***","3")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("**","2")}
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*","1")}
#Directories
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace(":","-")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("<","-")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace(">","-")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("?","-")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("/","-")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("|","-")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("**********","10")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*********","9")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("********","8")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*******","7")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("******","6")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*****","5")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("****","4")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("***","3")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("**","2")}
Get-ChildItem -Directory -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*","1")}
所以这工作正常,但由于某种原因,我在重命名文件夹时遇到很多错误,即使它工作正常...
错误:
… curse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace("*", …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Source and destination path must be different.
我也试过这个帖子 suggest 但这对我不起作用:
有人知道我为什么会收到此错误吗?以及如何修复它?
提前致谢。
这个错误是正常的,如果你没有理由重命名目录或文件,因为文件名是可以的,没有字符可以修改,名称保持不变,所以会显示一个错误,说你不能重命名一个file/directory同名。
尽管出现此错误,但过程并未停止,对最终结果没有影响
我建议您将所有键设置为搜索,对象中的新值:
#add your template to replace
$r = @{
":" = "-"
"<" = "-"
"**********" = "10";
"*********" = "9";
"********" = "8"
}
$Folders=Get-ChildItem -Directory -path -Recurse
foreach($folder in $Folders){
$newname = $folder.Name
foreach($k in $r.Keys){
$newname = $newname.Replace($k,$r.$k)
}
#rename only if original name and newname are differents
if(!$newname.equals($folder.Name)){
Rename-Item -Path $folder.FullName -NewName $newname
}
}
对你的文件做同样的事情......
您 运行 10 行代码每行仅重命名一种匹配类型,但实际上您 运行 相同的循环 10 次,在这种情况下,您的代码尝试重命名所有文件夹时间,但是当它尝试重命名具有相同 newName
的文件夹时出错,因为 Rename-Item
尝试重命名它,即使新名称与旧名称相同,它似乎没有一个验证器。
在这种情况下,“最便宜”的解决方案是添加 -ErrorAction SilentlyContinue
。但更复杂的解决方案是使用 if
语句或更适合案例 switch
.
更新:Regex
可能不是最容易处理的事情,因此下面的示例也说明了通配符 *
字符。
$allFolders=Get-ChildItem -Directory -Recurse
foreach($folder in $allFolders){
switch -Regex ($folder.Name){
'[:<>?\|]'{
$newName=$folder.Name.replace("[:<>?\|]","-")
Rename-Item -Path $folder.FullName -NewName $newName
}
'\*'{
$regexFormat = '\*'
$matchNumber=[regex]::Matches($folder.Name, $regexFormat) | ForEach-Object { $_.value }
$newName=$folder.Name.replace("*",$matchNumber.Count)
Rename-Item -Path $folder.FullName -NewName $newName
}
}
}
这样,您将 运行 1 次循环而不是 10 次循环,并且您只尝试重命名与您提供的模式相匹配的项目,因此与您使用的多行代码相比,您将看到显着的性能提升.
在我的 Windows 机器上,我不能在文件或文件夹名称中使用这样的字符,但理论上这应该可行:
(Get-ChildItem -File) | ForEach-Object {
$_ | Rename-Item -NewName {
# replace the '*' by the number of consecutive asterikses found
$name = $_.Name
$match = ([regex] '(\*+)').Match($name)
while ($match.Success) {
$name = $name -replace [regex]::Escape($match), $match.Length
$match = $match.NextMatch()
}
# finally replace the other special characters by a hyphen
$name -replace '[:<>?/|]', '-'
}
}
Get-ChildItem 周围的括号强制它在管道重命名之前完成收集。否则,您最终可能会尝试重命名已处理的项目