一個驅動器遷移 (One Drive Migration)


問題描述

一個驅動器遷移 (One Drive Migration)

我正在嘗試將文件服務器遷移到 One Drive,問題是有許多文件夾和文件帶有“|”等特殊字符 , '<' 等等。

而且出於某種原因,該公司使用'*'進行版本控制,例如:

'*' => v.1 '**' => v.2

etc...

所以我寫了一個 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.

我也試過這個線程 建議但這沒有 不適合我:

解決方案不起作用

有人知道我為什麼會收到此錯誤嗎?以及如何解決?

提前致謝。


參考解法

方法 1:

The error is normal, if you dont have reasons to rename the directory or file because the filename is ok and no character to modify, the name stays same, so an error is displayed saying you cant rename a file/directory with same name.

Despite this error, the process is not stopped and has no impact on the final result

i suggest you to set all couple key to search , new value in an object:

#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
    }
}

do samething for your files......

方法 2:

On my Windows machine I cannot have characters like that in a file or folder name, but theoretically this should work:

(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 '[:&lt;&gt;?/|]', '‑' 
}

}
</code></pre>

the brackets around Get‑ChildItem force it to complete the gathering before piping to rename. Otherwise, you may end up trying to rename items that were already processed

方法 3:

You run 10 lines of code to rename only 1 type of match per line but effectively you run the same loop 10 times, in this case your code try to rename all folders every single time, but it errors out when it tries to rename the folder with the same newName , because Rename‑Item tries to rename it even if the new name is the same as the old one, it appears to not have a validator for that.

In that case, the "cheapest" solution is to add ‑ErrorAction SilentlyContinue . But a more sophisticated solution would be to validate your dataset with an if statement or a more appropriate for the case switch .

Update : Regex might not be the easiest thing to deal with, so the example bellow account for the wildcard * character as well.

$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 

        }
    }
}

This way, you will run 1 loop instead of 10 and you only try to rename items that matches the pattern you provide, so you will see a significant performance increase compared to the multiline code you are using.

(by Wilson SilvaFrenchyTheoVasil Nikolov)

參考文件

  1. One Drive Migration (CC BY‑SA 2.5/3.0/4.0)

#onedrive #powershell #rename






相關問題

WP7-Skydrive API 下載任何文件並保存隔離存儲 (WP7-Skydrive API Download Any file and Save Isolated Storage)

如何編寫 .NET 控制台應用程序來訪問 SkyDrive? (How can I write a .NET console application to access SkyDrive?)

Loại đăng nhập Skydrive API Windows 8 (Skydrive API login type Windows 8)

如何使用 Rest api 和 oauth2.0 創建文件夾和上傳文件 (How to create folder and upload file using Rest api and oauth2.0)

從 ERP 保存到 OneDrive (Save to OneDrive from ERP)

適用於 Windows 通用 APP 的 OneDrive Api (OneDrive Api for Windows Universal APP)

一種 Drive / Office365 與 Google Apps Script 類似的腳本語言 (One Drive / Office365 similar scripting language as the Google Apps Script)

OneDrive API 瀏覽器 C# (OneDrive API browser C#)

從 Python 應用程序訪問 Microsoft Live 服務 (Access Microsoft Live services from Python application)

一個驅動器 api 安全 URL (One drive api secure url)

嘗試使用 get-PnPFile 從 OneDrive 獲取文件的所有版本時找不到文件 (File not found trying to get all versions of a file from OneDrive using get-PnPFile)

一個驅動器遷移 (One Drive Migration)







留言討論