目前正在尝试找出一种方法来重命名某个文件夹 ( /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\purchases
和d:\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
$_.BaseName
rni
重命名项目。
测试此解决方案(在线或本地)
最简单的方法是在线尝试此解决方案。
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 部分。
我会尽力回答下一个问题,以显示我的努力。无论如何,你们两个的回答都帮助我解决了这个问题。
再次感谢!