PowerShell:重命名/删除文件夹中可以出现在文件层次结构不同位置的文件

PowerShell:重命名/删除文件夹中可以出现在文件层次结构不同位置的文件

目前正在尝试找出一种方法来重命名某个文件夹 ( /root) 中的 PDF 文件,这些文件直接或间接位于purchases文件夹内,而文件夹本身又直接或间接位于该/root文件夹内。我想使用 PowerShell 实现这一点,但无法达到我在那里的众多主题上找到的示例的进一步效果。

例如,有以下目录结构:

/root/<subfolder1>/purchases/invoice1.pdf
/root/<subfolder1>/order.pdf
/root/<subfolder2>/purchases/invoice2.pdf

目的是仅重命名或删除位于“购买”文件夹中的 PDF 文件。不得触碰任何其他文件夹中的 PDF 文件。

名称<subfolderX>未知(即,它们可以是任何内容,例如“a”或“b”)。

该脚本需要递归运行所有文件夹。

任何为实现这一目标的指导都将不胜感激。

答案1

简短回答

d:\root要显示直接或间接包含在named的直接或间接子目录中的 PDF 文件的名称purchases,您可以使用:

gci -Directory -Recurse d:\root\purchases | % { gci -Recurse "$_\*.pdf" } | % FullName

简要说明:该命令递归查找d:\root名为的所有直接和间接子目录purchases,然后递归查找每个子目录中的所有 PDF 文件,然后返回每个 PDF 文件的完整路径。

其他用例

要删除这些 PDF 文件:

gci -Directory -Recurse d:\root\purchases | % { gci -Recurse "$_\*.pdf" } | ri

重命名这些 PDF 文件(例如,在基本名称上添加前缀和后缀):

gci -Directory -Recurse d:\root\purchases | % { gci -Recurse "$_\*.pdf" } | % { rni $_ "pref-$($_.BaseName)-suff.pdf" }

要删除purchases目录及其全部内容:

gci -Directory -Recurse d:\root\purchases | ri -Recurse

详细说明

  • gci获取子项
  • gci -Directory -Recurse d:\root\purchases返回全部目录( -Directory) 其名称为purchases是 的直接或间接 ( -Recurse) 子文件夹d:\root\。换句话说,它将返回d:\root\purchases(如果存在)以及d:\root\b\c\purchasesd:\root\a\purchases。这不是很直观,而且似乎没有在文档,但这是当前的行为(截至 PowerShell 6)。
  • %ForEach 对象{}。它为管道中的每个对象执行一个脚本块(括在花括号 ( ) 中)。
  • gci -Recurse "$_\*.pdf"检索先前找到的目录中直接或间接包含的 PDF 文件列表purchases
  • % FullName只是用来显示这些PDF文件的路径。
  • ri除去项目。它删除了先前计算的 PDF 文件列表(因为-Path该命令的参数Remove-Item接受管道输入)。
  • ri -Recurse允许删除先前计算的purchases目录列表及其内容。
  • rni $_ "pref-$($_.BaseName)-suff.pdf"在管道中当前文件(即我们要查找的每个 PDF 文件)的基本名称中添加前缀 ( pref-) 和后缀 ( )。文件的基本名称是不带扩展名的文件名称,是-suff$_.BaseNamerni重命名项目

测试此解决方案(在线或本地)

最简单的方法是在线尝试此解决方案

test否则,您可以在文件夹中创建示例目录结构当前工作目录,使用以下代码片段(当心:如果当前目录中.\test已有文件夹,则更改为其他内容):test

mkdir -ErrorAction SilentlyContinue .\test\a\purchases, .\test\a\e\, .\test\b\c\purchases\
Out-File .\test\a\purchases\invoice1.pdf
Out-File .\test\a\order1.pdf
Out-File .\test\a\e\order2.pdf
Out-File .\test\b\c\purchases\invoice2.pdf
Out-File .\test\b\c\purchases\invoice3.pdf

要查看此目录结构中的所有文件,可以使用:

gci -Recurse -File .\test | % FullName

将会返回类似这样的内容:

D:\test\a\order1.pdf
D:\test\a\e\order2.pdf
D:\test\a\purchases\prefix-invoice1-suffix.pdf
D:\test\b\c\purchases\prefix-invoice2-suffix.pdf
D:\test\b\c\purchases\prefix-invoice3-suffix.pdf

(其中D:被替换为您当前的工作目录。)

执行作为答案提供的命令(gci -Directory -Recurse .\test\purchases | % { gci -Recurse "$_\*.pdf" } | % FullName),将显示需要移除或删除的文件:

D:\test\a\purchases\invoice1.pdf
D:\test\b\c\purchases\invoice2.pdf
D:\test\b\c\purchases\invoice3.pdf

测试后进行清理:

rm -Recurse .\test

答案2

Youssef Abidi 给了你一个针对单个驱动器的答案,但你似乎在说 .\purchases 文件夹的路径是未知的?

然而,论坛的规则是,您必须提供您尝试过的方法和遇到的错误,这样您才能展示您的最终目标,而不是让我们猜测,就像大多数人会说的那样“为您完成工作”。这里的人非常乐于助人,但是,你知道的。

话虽如此,如果我的假设是正确的。本质上,对主机上任何驱动器上的购买文件夹进行过滤,然后对该文件夹中的 pdf 进行过滤,然后按您的意愿进行操作。

这实际上只是一个单行流水线命令 - 如果上述是一个有效的假设

(Get-PSDrive).Root -like '*:\' | 
% { (Get-ChildItem -Path ((Get-ChildItem -Path $_ -recurse -Filter Purchases -Directory -ErrorAction SilentlyContinue).FullName) -Filter '*.pdf' -Verbose).FullName }

# Results

C:\purchases\powershell-cheat-sheet.pdf
C:\purchases\PSPunctuationWallChart_1_0_4.pdf
D:\Temp\purchases\powershell-cheat-sheet.pdf
D:\Temp\purchases\PSPunctuationWallChart_1_0_4.pdf

当然,你可以把这个一行代码分解成不同的东西。

答案3

我同意做好功课对社区来说很重要。我通过 gci 和 filter 弄清楚了很多问题,但无法即兴发挥引号之间的双 gci 部分。

我会尽力回答下一个问题,以显示我的努力。无论如何,你们两个的回答都帮助我解决了这个问题。

再次感谢!

相关内容