PowerShell:根据扩展名移动文件

PowerShell:根据扩展名移动文件

以下脚本可以运行,但速度非常慢。有人有更快的解决方案吗?

简而言之,我有一个装满恢复文件的文件夹(4M+)。我想根据扩展名为每个文件创建一个子文件夹,并将文件移动到那里。正如我所说,以下脚本非常慢。

get-childitem -file | ForEach-Object -parallel {$ext=$_.Extension; mkdir $ext; mv $_ .\$ext\} -throttlelimit 32

不管它是按照书写的方式并行运行还是不并行运行,它都很慢。

谢谢!


更新

这个问题在版本 7 中无论是否启用并行都会出现。在版本 7 中,如果不启用并行,则每个文件大约需要 15 秒。

我刚刚尝试了版本 5 中的脚本(显然没有并行),它每秒处理超过 100 个文件。

因此,这个问题现在只是理论上的问题。运行版本 5 中的脚本速度相当快,按照目前的速度,应该可以在不到 15 分钟的时间内完成 4M 以上的文件。

为什么版本 7 对于以下脚本每个文件需要 15 秒左右的时间:

get-childitem -file | ForEach-Object {$ext=$_.Extension; mkdir $ext; mv $_ .\$ext\}

答案1

尝试通过首先创建文件夹,然后使用一个命令移动每个扩展名的文件来提高速度:

$extensions = Get-Childitem | Select-Object -Unique @{label='ext';expression={$_.Extension.substring(1)}}
$extensions | foreach {New-Item -ItemType directory -Name $_.ext}
$extensions | foreach {mv "*.$($_.ext)" "$($_.ext)"}

答案2

我建议您首先创建在文件夹中找到的所有扩展名的数组(不带前导点),然后使用 robocopy 移动文件,同时创建子目录:

$sourceFolder = $PSScriptRoot  # specify the path where the files are now

# get a unique array of all file extensions found in the source folder
$extensions = (Get-ChildItem -Path $sourceFolder -File | Group-Object {$_.Extension.TrimStart(".")}).Name
# loop through the extension array and have robocopy do the copying for you
foreach ($ext in $extensions) {
    $targetDir = Join-Path -Path $sourceFolder -ChildPath $ext
    robocopy $sourceFolder $targetDir "*.$ext" /MOV /NFL /NDL /NJH /NJS /NC /NS /NP /R:0 /W:0 > $null
}

答案3

您现有的命令可能会尝试为每个文件和扩展名创建一个目录,因此如果文件夹中有 1000 个 PDF 文档,它会运行该命令 1000 次来创建一个.pdf子文件夹。

通过命令-Unique的参数Select,它仅针对每个不同或唯一的文件扩展名值运行一次该命令,以创建具有点扩展名的文件夹(例如c:\ParentFolder\.pdf)。

我只需将所有“唯一”的文件扩展名值通过管道传输到另一个循环New-Item,然后使用该-Force参数即可。如果可能的话,尽量避免将另一个变量混入其中。

下一部分我将运行该Get-ChildItem命令并将其循环到命令中Move-Item,将具有匹配扩展名的文件移动到名为相同点扩展名的子文件夹。

Get-ChildItem -File | % { Process { $_.Extension }} | Select -Unique | % { Process { New-Item $_ -ItemType Directory -Force }};
Get-ChildItem -File | % { Process { Move-Item $_ -Destination $_.Extension -Force }};

支持资源

相关内容