Powershell:删除每 n 个文件

Powershell: Delete Every n Files

我刚刚导入了一堆图片,发现每张图片有3个副本,但它们是按顺序命名的。

这三个文件基本上是一样的:

P5240901.dng
P5240902.dng
P5240903.dng

还有,大约 1600 张图片。

我正在考虑编写一个简单的 PowerShell 脚本(我使用 Windows)来查看这些文件的目录,并从三个文件中保留一个文件,只是循环访问一系列文件。 我在我的文件之前没有找到可以处理 'P' 字符的东西,而且我不熟悉 PowerShell 语言。

有什么想法吗? 谢谢!

尝试以下方法,这将仅保留每组文件中的第一个文件,其名称除了文件扩展名之前的最后一个字符外都是相同的,假设该字符是数字(语法假定为 PSv3+):

'P5240901.dng', 'P5240902.dng', 'P5240903.dng', 'A1.dng', 'A2.dng', 'singleton.dng' | 
  Group-Object { $_ -replace '^(.+)\d\.', '' } | 
   ? Count -gt 1 |
     % { $_.Group[1..$($_.Group.Count)] }

产量:

P5240902.dng
P5240903.dng
A2.dng

用对 Get-ChildItem -File 的调用替换示例输入数组,并在 $_.Group[1..$($_.Group.Count)] 前面添加 Remove-Item 以执行实际删除。

上述命令使用 string 数组,输入 filenames,但 [System.IO.FileInfo] 实例输出by Get-ChildItem 将在字符串上下文中有效地执行相同的操作:它们将扩展为各自的文件名。

此解决方案的优势在于它不依赖于严格以 3 个为一组出现的输入文件:

  • 除了文件扩展名前的数字之外,任何一组共享相同名称且至少有 2 个成员(以及超过该数字的任何数字)的输入文件都将删除除第一个成员以外的所有成员。
  • 任何其他文件保持不变。

解释:

  • Group-Object { $_ -replace '^(.+)\d\.', '' }

    • 按输入文件共享的文件名部分有效地对输入文件进行分组(但前提是它们共享除了文件扩展名之前的最后一个字符以外的所有内容,并且该字符是数字)。
  • ? Count -gt 1

    • 仅传递至少有 2 名成员的结果组。
  • % { $_.Group[1..$($_.Group.Count)] }

    • 处理每个组的文件,第一个除外。

更新: 这是 OP 稍后评论提示的一个变体: 下面,给定输入文件名如P5240901.dng, P5240902.dng, ..., P5240910.dng, P5240911.dng, ..., P5240990.dng, P5240991.dng, ..., P5240999.dng,将每组10个文件视为一组(以十位为准),每组内只保留第一个文件:

1..99 | % { "P52409$('{0:00}' -f $_).dng" } | 
  Group-Object { $_ -replace '^(.+\d)\d\.', '' }   | 
   ? Count -gt 1 |
     % { $_.Group[1..$($_.Group.Count)]}

产量:

# tens place of 0; skips ...01.dng
P5240902.dng
P5240903.dng
... # up to ...09.dng
# tens place of 1; skips ...10.dng
P5240911.dng
P5240912.dng
... # skips ...20.dng, ...30.dng, ...
# tens place of 9; skips ...90.dng
P5240991.dng
P5240992.dng
...
P5240999.dng

为了只将感兴趣的文件传递给命令,将示例输入数组替换为
Get-ChildItem P52515[0-9][0-9].dng.

假设目录中的所有内容都遵循命名约定并且在一组 3 中,这样的事情应该有效:

$mydir = 'C:\path\to\files'
[int]$idx = 1
get-childitem $mydir|sort-object {$_.Name} |foreach-object{
    if ($idx % 3 -ne 1){ #get the modulus
        $_ |remove-item
    }
    $idx++
}