将文件夹拆分成一定大小的文件夹
我试图将文件夹拆分成最大大小为8GB的文件夹。将文件夹拆分成一定大小的文件夹
启动文件夹:
Folder 1
2KB file
2GB file
7GB file
Folder 2
1GB file
5.6GB file
Folder 3
8GB file
,我想变成:
Folder A (~7.6GB)
Folder 1
2KB file
2GB file
Folder 2
5.6GB file
Folder B (8GB)
Folder 1
7GB file
Folder 2
1GB file
Folder C (8GB)
Folder 3
8GB file
的目标是,你可以将文件夹,并得到原来的文件夹结构。
这是甚至可能与PowerShell的东西?我已经看到了一些使用bash和dirsplit的解决方案,但是我真的很想将它保留在powershell中,除非有一些已经存在的软件有一个简单而干净的解决方案。
我忘了补充说,文件夹可能不仅包括文件,但有时也包括文件夹。有一种解决方案在某种程度上递归地实现吗?
这感觉就像我错过了一些东西,考虑到我没有用PowerShell工作过很多。
您描述的分区类型也称为bin packing problem。
一个相当快地解决了这个被称为第一配合算法 - 想象有限的大小的二进制位的无限线,并且简单地把每项到具有余地它下一箱。这可以通过首先将最大的物品(通过预先分拣物品)进一步优化。
下面是一个有点冗长的实现:
# Define the root path (the one that contains Folder1, Folder2 etc)
$RootPath = 'C:\data'
# Define the target path (where we'll create the new structure)
$TargetPath = 'C:\packed'
# Collect the file information, order by descending size (largest first)
$Files = Get-ChildItem $RootPath -File -Recurse |Sort-Object Length -Descending
# Define max bin size as the size of the largest file
$Max = $Files[0].Length # puth 8GB here instead (fiels larger than 8GB will end up in a lone bin)
# Create a list of lists to group our files by
$Bins = [System.Collections.Generic.List[System.Collections.Generic.List[System.IO.FileInfo]]]::new()
:FileIteration
foreach($File in $Files){
# Walk through existing bins to find one that has room
for($i = 0; $i -lt $Bins.Count; $i++){
if(($Bins[$i]|Measure Length -Sum).Sum -le ($Max - $File.Length)){
# Add file to bin, continue the outer loop
$Bins[$i].Add($File)
continue FileIteration
}
}
# No existing bins with capacity found, create a new one and add the file
$NewBin = [System.Collections.Generic.List[System.IO.FileInfo]]::new()
$NewBin.Add($File)
$Bins.Add($NewBin)
}
# Now go through the bins and move the files to the new directory
foreach($Bin in $Bins){
# Create a new randomly named folder for the files in the bin
$Directory = New-Item $TargetPath -Name $([System.IO.Path]::GetRandomFileName()) -ItemType Directory
foreach($File in $Bin){
# Recreate the parent folder inside the new folder if it doesn't already exist
$ParentName = $File.Directory.Name
$ParentPath = Join-Path $Directory.FullName -ChildPath $ParentName
if(-not(Test-Path $ParentPath)){
$ParentDirectory = New-Item $ParentPath -ItemType Directory
}
# Move file into new directory structure
Move-Item $File.FullName -Destination $ParentPath
}
}
你可以平凡跳过分配每个项目列表的中间步骤,而直接进入到移动的文件,但我觉得分裂例如引入两个使得它更清晰/更具可读性我们正在尝试做的事情。
击败我!非常好':-)' – gvee
我很欣赏这种努力,谢谢! –
我不认为你错过了任何东西。这是这些似乎微不足道的问题之一,但实际上很难找到最佳的解决方案。你是否试图将数据放入一组有限的文件夹中(即将它们分成3个文件夹)或有限大小(每个文件夹中最多8GB)? –
以最大的文件(效率)开始的algorythm会得到相同的结果,但顺序不同。 – LotPings
@ MathiasR.Jessen我想将它们拆分成尽可能少的文件夹。 –