簡體   English   中英

Powershell - 遞歸地重命名文件,將上層文件夾作為前綴添加到 NewName

[英]Powershell - Rename files recursively adding upper folder as prefix to NewName

我有這種樹文件夾結構:

c:\Loc_2636\08\20220801.csv
c:\Loc_2636\06\20220607.csv
c:\Loc_2538\07\20220701.csv

我想添加到上層“Loc_*”文件夾的任何文件后綴。 最后他們應該是這樣的:

c:\Loc_2636\08\Loc_2636_20220801.csv
c:\Loc_2538\07\Loc_2538_20220701.csv

我認為這很簡單,但我遇到了麻煩,因為如果我這樣做:

Get-ChildItem -File -Recurse  | % { Rename-Item -Path $_.PSPath -NewName $_.FullName.Split("\")[5]+"_"+$_.Name -WhatIf} 

引發此錯誤:找不到接受參數“+_+20220701.csv.Name”的位置參數。

相反,如果我嘗試通過 function

function rena(){
    param ([string]$name, [string]$fullpath)
    $arr=$fullpath.Split("\")
    foreach($tmp in $arr)
        {
            if($tmp.ToString().Contains("Loc_")){
                $found=$tmp;
                }
        }
    return $found+"_"+$name
}
Get-ChildItem -File -Recurse  | % { Rename-Item -Path $_.PSPath -NewName {rena($_.Name,$_.FullName) -WhatIf}} 

引發另一個錯誤

無法評估參數“NewName”,因為它的參數被指定為腳本塊並且沒有輸入。 沒有輸入就無法評估腳本塊。

我很困惑,因為我已經在 Get-ChildItem 命令中使用了 function 但我從未收到此錯誤。

預先感謝您的任何幫助。

你可以這樣做:

Get-ChildItem -File -Recurse | Where-Object { $_.DirectoryName -match '\\(Loc_\d+)' } | 
Rename-Item -NewName { '{0}_{1}' -f $matches[1], $_.Name } -WhatIf

如果控制台中顯示的內容正常,請移除-WhatIf開關。 然后再次運行以實際開始重命名文件。

為防止重命名已重命名的文件(多次運行時),請將 Where-Object 子句擴展到Where-Object { $_.DirectoryName -match '\\(Loc_\d+)' -and $_.Name -notlike 'Loc_*' }

Theo 的有用答案為您的任務提供了一個更好的解決方案,可以繞過您的語法問題。

至於您嘗試的問題

為了表達式(例如, $_.FullName.Split("\")[5]+"_"+$_.Name )或命令調用(例如, rena $_.Name $_.FullName )作為arguments 傳遞對於命令,您必須將它們括在(...) 分組運算符中。

  • 雖然孤立的簡單表達式(例如$foo$foo.Bar$foo.ToUpper()不需要(...) ,但任何更復雜的表達式都需要。

    • 有關如何將未引用/未包含在(...)中的標記解析為 arguments 的完整規則,請參閱此答案
  • {... }中包含一個參數會創建一個腳本塊- 一段可重用的按需調用代碼; 該代碼不會立即執行,因此它不是(...)的替代品(如果您將腳本塊傳遞給[string]類型的參數,您將獲得它的逐字內容,無{} )。 但是,像 arguments 這樣的腳本塊對於使用稱為延遲綁定腳本塊的技術基於管道輸入動態計算參數值很有用,如 Theo 的答案所示。

最后,請注意,我已經重新制定了您的 function 調用
rena($_.Name,$_.FullName)
rena $_.Name $_.FullName ,因為只有后者按預期工作:

  • PowerShell 命令- 函數、cmdlet、腳本和外部程序 -必須像 shell 命令一樣調用- foo arg1 arg2 -不像C#arg2 foo('arg1', 'arg2')方法 -
  • 也就是說,在 arguments 列表周圍沒有(...) ,並且使用空格而不是,來分隔 arguments。
    • 如果您使用,來分隔 arguments,您將構建一個命令將其視為單個參數數組
  • 有關更多信息,請參閱此答案

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM