2014-02-19 36 views
1

我有一個文件夾結構,我想通過任何時候文件夾名稱包含「&」,我想用「和」替換它。我認爲這是可能的PowerShell,但我非常noobie談到PowerShell。用PowerShell遞歸替換符號

謝謝!

這裏是我的嘗試:

get-childitem -recurse ./ *&* | where-object { $_.Name -like "*&*" } | % {rename-item $_ -newname $_.Name.Replace("&","and") -whatif} 

將這隻改變文件夾名稱?

也試過這一個,但沒有運氣是(這一次給出了錯誤:不能重命名,因爲指定的目標代表了一個路徑或設備名稱:

gci -recurse | where-object { $_.Name -like "*&*" } | ?{ $_.PSIsContainer } | % {rename-item $_FullName $_FullName.Replace("&","and")} 

編輯:POWERSHELL在Windows Server 2008 R2

+0

在哪些方面你的嘗試沒有成功?你得到的錯誤是什麼,你試圖解決什麼錯誤?另外,您使用的是哪個PowerShell版本? –

+0

請參閱編輯。謝謝! – shenn

回答

2

我懷疑一個原因origi nal代碼失敗是因爲Rename-Item被賦予了一個包含整個路徑的NewName參數,而不僅僅是名稱。次要問題在於代碼將嘗試從頂部向下重命名,這可能會使流水線中的其他對象失效。我試圖通過首先處理最長的路徑來解決這個問題(因此在PSPath.length上降序排列)。它在我的測試文件夾上工作。

get-childitem ./ -Recurse -Filter "*&*" | 
    ? { $_.PSIsContainer } | 
    sort { ($_.PSPath).length } -Descending | 
    % { 
     $_ | Rename-Item -NewName ($_.Name -replace "&","and") 
    } 
+0

因爲如果父項已重命名,DirectoryInfo對象'$ _。FullName'將使用父項的更新路徑,所以文件夾重命名沒有問題。問題是'_ _。FullName.Replace(「&」,「and」)'想移動項目,而不是重命名項目。您的解決方案運行良好,但排序是不必要的,可以刪除。 –

+0

謝謝羅伯特。我再次測試,評論這種排序,並失敗。告訴我'找不到路徑的一部分'。當我查看測試目錄樹的狀態時,它是最深的目錄失敗了。 – andyb

+0

羅伯特 - 我試着對你的代碼進行測試,結果也失敗了。我的目錄結構如下: \ A&B \ C \ C \ A&B \ C \ A&B \ E和F \ C \ C&d – andyb

0

你是在正確的道路上創造下了幾個測試文件夾和文件。「C:\ TEMP \ AAA」文件夾,以顯示它是如何工作

PS C:\> gci C:\Temp\aaa -recurse | where {$_.name -match '&'} | Rename-Item -newname {$_.name -replace '&','and'} -whatif 
What if: Performing the operation "Rename Directory" on target "Item: C:\Temp\aaa\ad & il Destination: C:\Temp\aaa\ad and il". 
What if: Performing the operation "Rename Directory" on target "Item: C:\Temp\aaa\ad & il\hin\di&st&t Destination: C:\Temp\aaa\ad & il\hin\diandstandt". 
What if: Performing the operation "Rename File" on target "Item: C:\Temp\aaa\ad & il\hin\adilll&hindist &an.txt Destination: C:\Temp\aaa\ad & il\hin\adilllandhi ndist andan.txt". 
1

原因你的錯誤是,你替換整個路徑的&性格,甚至父文件夾。

說例如您要重命名文件夾c:\me & my\something & another您的$ _。FullName.Replace(「&」,「和」)會將其更改爲c:\me and my\something and another。然而,由於我們在這個小測試場景中重命名了父文件夾之前的子文件夾,所以我們實際上試圖將移動到將該文件夾從c:\my & my的孩子變成了c:\me and my的孩子(並且最重要的是我們要移動它到一個文件夾不存在

從上Rename-Item幫助部分(我得到了通過執行Get-Help Rename-Item -Parameter NewName):

Specifies the new name of the item. Enter only a name, not a path and name. If you enter a path that is different 
from the path that is specified in the Path parameter, Rename-Item generates an error. To rename and move an item, 
use the Move-Item cmdlet. 

所以我們只希望包括在NewName參數的文件夾的名稱。

最後,正如@andyb指出的那樣,我們還需要按照子文件夾,然後是父文件夾的順序重命名這些項目,以確保父路徑仍然完好無損。 @andyb建議的按照FullName路徑長度對文件夾進行排序的解決方案應該適用於此目的。

因此以下應該工作得很好。

Get-ChildItem .\ -Recurse -Filter "*&*" | 
    Where { $_.PSIsContainer } | 
    Sort { $_.FullName.Length } -Descending | 
    Foreach { 
     $newName = $_.Name.Replace("&", "and") 
     Rename-Item $_.FullName $newName 
    } 

編輯:更新以包括在文件夾路徑長度遞減的次序排序,由於其@andyb指出一個misstake。

0

步驟: 1.比賽項目

  1. 反向項目,使我們可以從孩子重新命名他們的父

  2. 將其重命名

代碼:

$matchedItems = ls D:\test -Recurse | where { $_.Name -like '*&*' } 

[array]::Reverse($matchedItems) 

$matchedItems | foreach { 
    $newName = "" 
    if($_.PSIsContainer){ 

    $newName = Join-Path $_.Parent.FullName ($_.BaseName -replace '&' , 'and') 
    } 
    else { 

    $newName = Join-Path $_.Directory.FullName ($_.BaseName -replace '&' , 'and') 
    } 


    $_ | Rename-Item -NewName $newName 
} 

輸出:

PS C:\> ls D:\test -Recurse | select FullName 

FullName                             
--------                             
D:\test\& New Foder                          
D:\test\New & folder                          
D:\test\New folder&                          
D:\test\test & test.txt                         
D:\test\& New Foder\New & folder                       
D:\test\& New Foder\New folder&                       
D:\test\& New Foder\test & test.txt                      
D:\test\New folder&\& New Foder                       
D:\test\New folder&\New & folder                       
D:\test\New folder&\New folder&                       
D:\test\New folder&\test & test.txt                      
D:\test\New folder&\& New Foder\New & folder                    
D:\test\New folder&\& New Foder\New folder&                    
D:\test\New folder&\& New Foder\test & test.txt                   



PS C:\> $matchedItems = ls D:\test -Recurse | where { $_.Name -like '*&*' } 
[array]::Reverse($matchedItems) 

$matchedItems | foreach { 
    $newName = "" 
    if($_.PSIsContainer){ 
    $newName = Join-Path $_.Parent.FullName ($_.BaseName -replace '&' , 'and') 
    } 
    else { 

    $newName = Join-Path $_.Directory.FullName ($_.BaseName -replace '&' , 'and') 
    } 


    $_ | Rename-Item -NewName $newName 
} 



PS C:\> ls D:\test -Recurse | select FullName 

FullName                             
--------                             
D:\test\and New Foder                         
D:\test\New and folder                         
D:\test\New folderand                         
D:\test\test and test                         
D:\test\and New Foder\New and folder                      
D:\test\and New Foder\New folderand                      
D:\test\and New Foder\test and test                      
D:\test\New folderand\and New Foder                      
D:\test\New folderand\New and folder                      
D:\test\New folderand\New folderand                      
D:\test\New folderand\test and test                      
D:\test\New folderand\and New Foder\New and folder                  
D:\test\New folderand\and New Foder\New folderand                  
D:\test\New folderand\and New Foder\test and test  
+0

如果通過for從長度-1到0訪問匹配的項目,也可以跳過[array] :: Reverse($ matchedItems) –