2017-09-05 70 views
2

我正在嘗試使用逗號分隔值重命名PDF文件。當所有我的PDF文件是一個文件夾中,下面的腳本工作:使用if()重命名子文件夾中的文件

$myHeader = echo fileName newName 

Import-Csv $PSScriptRoot\list_names.txt -Header $myHeader | foreach { 
    if (Test-Path -Path $PSScriptRoot\*.pdf) { 
     Rename-Item $_.fileName $_.newName 
    } 
} 

然而,重組PDF文件到子文件夾後,該腳本將不再有效,因爲PDF文件的路徑現在$PSScriptRoot\subfolder1\*.pdf$PSScriptRoot\subfolder2\*.pdf等。

Test-Path不適用於子文件夾,而且我也嘗試使用Get-ChildItem和其他命令更改腳本無濟於事。我不知道如何解決這個腳本來處理子文件夾。

編輯:我只有CSV中的文件名。它只有兩列:

 
"oldfilename.pdf","newfilename.pdf" 
+0

所以在你的csv中,你只有文件名還是你有文件名和子文件夾? –

+0

是的,有一個CSV記錄的例子會很有用。另外,您是否使用-Recurse開關嘗試Get-ChildItem?您需要添加該開關以獲取枚舉的子文件夾內容。 –

+1

@MaximeFranchot我編輯了我的問題以顯示CSV中的記錄示例。 –

回答

2

這是我想出來的。它將CSV內容放入一個使用Key = OldName,Value = NewName的哈希表中。然後,它會遍歷根路徑中的所有子文件夾。如果需要,可以使用-exclude-include參數,或者刪除-recurse參數等,以使搜索更快更精確。

$CSVHashTable = @{} 
Import-CSV $PSScriptRoot\list_names.txt | 
%{$CsvHashTable.Add($_.FileName, $_.NewName)} 

Get-ChildItem -Path $PSScriptRoot -File -Recurse | 
?{$CsvHashTable.ContainsKey($_.Name)} | 
Rename-Item {$CsvHashTable.Item($_.Name)} 
+0

另外,Hashtable可防止添加多個具有相同名稱的文件(但不同的子文件夾)。您可能會在第三行的'.Add'方法之後獲得此信息。 –

+0

感謝您的回覆,但我不熟悉哈希表。當我試圖運行這個時,我收到一條錯誤消息:「異常調用」添加「與」2「參數:」鍵不能爲空。「」 –

+0

這很奇怪,它似乎是您的CSV問題。如果你執行'Import-CSV $ PSScriptRoot \ list_names.txt',會發生什麼?它是否正確輸出CSV的內容?如果您執行Import-CSV $ PSScriptRoot \ list_names.txt |,那麼如何?選擇-ExpandProperty FileName'?這將檢查「FileName」是否是正確的標題,我不能告訴你它是否正確:P –

4

如果你知道所有感興趣的文件直接位於腳本的文件夾的直屬子文件夾,您可以使用Resolve-Path找到感興趣的每個文件:

$myHeader= 'fileName', 'newName' 

Import-Csv $PSScriptRoot\list_names.txt -Header $myHeader | ForEach-Object { 
    if ($file = Resolve-Path "$PSScriptRoot\*\$($_.filename)") { 
    Rename-Item $file $_.newName -WhatIf 
    } 
} 

如果沒有找到匹配的文件在任何直接子文件夾中,Resolve-Path調用不輸出任何內容,並且不輸入if塊。如果匹配,則將其分配給變量$file,並輸入if塊。

-WhatIf以前的重命名操作;刪除它來執行實際的重命名。


如果相反,感興趣的文件可以在任何地方腳本的文件夾樹的位置,用Maxime Franchot's helpful answer

+0

你確定這隻適用於直接的子文件夾嗎?我認爲通配符「*」可以代表「子文件夾\ subsubfolder」,使它可以在路徑中的所有級別。但是,無論如何感謝鏈接;) –

+0

@MaximeFranchot:是的,它只適用於直接的子文件夾:'*'只覆蓋文件夾層次結構的_一級。舉例來說,'bash'(v4 +)有'globstar'選項,這樣**就匹配整個子樹,但據我所知,PowerShell在其通配符模式語法中沒有等價物。 – mklement0

+1

我希望很明顯,我只是說出我的想法,所以謝謝你的更正:) –

0

使用內置這樣

ss1.pdf,tt1.pdf          
Sub1\ss2.pdf,tt2.pdf         
Sub1\Sub2\ss3.pdf,tt3.pdf 

下面的腳本不正確的工作CSV文件。

function Rename-Pdfs($Path,$items) { 

foreach ($item in $items) { 
    $OldName = $Path + $item.fileName  


    if (Test-Path $OldName) { 
     Rename-Item $OldName $item.newName 
    } 
} 
} 


$myHeader = echo fileName newName 
$csv = Import-Csv 'C:\__tmp\MyCSV.csv' -Header 'fileName','newName' 


Rename-Pdfs -Path 'C:\__tmp\' -items $csv 

,不使用的功能,並與PSScriptRoot

$items = Import-Csv 'C:\__tmp\MyCSV.csv' -Header 'fileName','newName' 

foreach ($item in $items) { 

    $OldName = $PSScriptRoot + '\' + $item.fileName  

    if (Test-Path $OldName) { 
     Rename-Item $OldName $item.newName 
    } 
} 

留意了,在這最後一個例子,我修改$ oldPath包括未加入PsScriptRoot,而不是我的CSV內,否則缺少反斜槓第一列(文件名)。

如果仍然有問題,請嘗試包含一些寫入主機命令,以便通過查看值可以更深入地瞭解此問題。

+0

你正在解決一個不同的問題。 OP聲明CSV文件只包含文件名,沒有路徑。 – mklement0

+0

OP提到一些文件在子文件夾中。我認爲它們是在相對於根文件夾的文件名中引用的。否則,我想這個解決方案是遞歸的,直到找到這個名字,但是如果你只根據名字進行重命名,而不是對位置進行一些引用,那麼它可能會在2個不同文件夾級別命名的文件中產生問題。 –