2017-09-05 128 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个不同文件夹级别命名的文件中产生问题。 –