2013-08-18 36 views
3

我是PowerShell的新手,最近我嘗試重命名文件夾中的120個文件,並遇到奇怪的行爲。PowerShell批量文件重命名中的奇怪行爲

我有什麼是從0001.txt,0002.txt,... 0120.txt命名的文件共120個文件。我想在每個文件名前添加一個'a'。我想出了這個命令:

ls | ren -newname {$_.name -replace '(\d+)','a$1'} 

但執行後,我得到了許多錯誤是這樣的:

「指定的路徑,文件名,或者兩者都太長完全合格的文件名必須小於260"

當我看着我的文件夾中,我得到的是從

aaaaaaaaaaaaaaaaaaaaaaaaa(repeat until it hit system limit on path length)....a0001.txt 
... 
... 
... 
aaaaaaaaaaaaaaaaaaaaaaaaa(repeat until it hit system limit on path length)....a0120.txt 
文件名

使用-cf開關進行進一步檢查後,事實證明,PowerShell將遞歸嘗試重命名過程。第一次重命名所有120個文件後,它再次將命令應用於a0001.txt,在文件名前有效地添加了另一個'a'。這一直持續下去,直到達到路徑長度限制並報告錯誤。

任何人都可以告訴我,如果我的重命名命令有什麼問題嗎?

回答

3

管到FOREACH-對象(速記%{})到質重命名文件。如果你只是想前面加上字母一個將每個文件名,你並不需要一個正則表達式,所有你需要做的是這樣的:

Get-ChildItem | %{Rename-Item $_ ('a' + $_.name)} 

用你喜歡的別名:

ls | %{ren $_ ('a' + $_.name)} 

要用正則表達式來做,使用($_.name -replace '^','a')更簡單。如果使用正則表達式的原因是目錄中有其他文件,並且您只想重命名以一串數字和.txt擴展名命名的文件,請注意您正在使用的正則表達式會預先計劃一個a到任何連續數字串。例如,agent007.txt將被重命名爲agenta007.txt。你應該只用你想要的格式匹配正則表達式:'^(\d+)\.txt'

還要注意,通過使用正則表達式在-NewName說法代替,你重命名不正則表達式匹配相同的名稱,它已經擁有的每個文件。沒什麼大不了的120個文件,但我會過濾文件提前上市:

Get-ChildItem | ?{$_ -match '^(\d+)\.txt'} | %{Rename-Item $_ ('a' + $_.name)} 

UPDATE:似乎有使用PowerShell 3.0中的錯誤,可能會導致批量重命名文件失敗在某些條件下。如果通過將目錄列表重命名爲Rename-Item來重命名文件,則任何文件被重命名爲按字母順序高於其當前名稱的文件都將通過其新名稱進行重新處理,因爲它稍後在目錄列表中遇到。這可能會導致相同的文件重複重命名,直到完整路徑的長度超過260個字符的最大值並引發錯誤。

例如,請注意,如果附加字母a而不是前置,則沒有問題。如果文件被命名爲B0001B0002等,一個被預先計劃,不會出現重複的再處理信

Get-ChildItem | %{Rename-Item $_ ($_.name + 'a')} 

:這適用於任意數量的文件。但是,如果前置字母c確實存在。

以下命令將單個一個到任意數量的文件的開頭,如果他們的名字與b開始:

Get-ChildItem | %{Rename-Item $_ ('a' + $_.name)} 

由於相同的文件,其名稱與B開頭,下面的命令預先考慮信ç反覆直到達到長度限制:

Get-ChildItem | %{Rename-Item $_ ('c' + $_.name)} 

這隻發生在包含一定數量或更高文件的列表中。 OP表示,如果他將文件數量減少到20個以下,他就沒有問題。我發現閾值爲37(36個文件或更少,不會發生重新處理)。我還沒有確定所有適用案例的數字是否相同,還是取決於更具體的因素。

稍後我會詳細說明這一點,並且一旦我更確切地確定了此問題的參數,就向Microsoft提交錯誤報告。

解決方法:過濾器從上市獲取-ChildItem位置對象使得新的文件名被排除在外。在更新部分之前,上面的命令的最後一個版本在PowerShell 3.0中工作。據推測,重新命名的文件通過新名稱重新引入到管道中,並再次處理,但由於新名稱與篩選器?{$_ -match '^(\d+)\.txt'}不匹配,所以它們在第二次通過管道時不會重命名,並且不會再次重新處理。

+0

感謝您的回答,您的解釋對於像我這樣的新手來說非常翔實。你的命令在PowerShell版本2上工作(如我的)。但它在PowerShell的版本3上給出了相同的行爲。我可以知道您使用的是哪個版本的PowerShell?而在版本3中,如果我將該文件夾中的文件減少到20個文件,這種奇怪的行爲就不會出現。我可能剛剛在PowerShell中發現了一個錯誤,或者我有一個錯誤的內存芯片 –

+0

哇,你是對的!這*是* PS 3中的一個錯誤。我在兩個版本中進行了測試,但只有少量的文件。隨着數量的增加,看起來正在發生的事情是,如果一個文件被重新命名爲按字母順序排列的更高的文件,它會再次用新名稱進行處理 - 這種情況會在相同的文件中反覆出現。評論太長,但我會更新我的答案,並向Microsoft提交錯誤報告。現在,我可以告訴你,我的答案中的最後一個版本和** where過濾器一起工作,因爲新名稱與模式不匹配,因此不會重新處理。 –

+0

感謝您的反饋和漫長的更新。感覺自己是第一個發現bug的人。 :)只是想知道爲什麼這個bug還沒有被帶出來。 –