Lau*_*ebs 5 windows powershell
我正在尝试将一个文件夹划分为最大大小为 8 GB 的文件夹。
起始文件夹:
Folder 1
2KB file
2GB file
7GB file
Folder 2
1GB file
5.6GB file
Folder 3
8GB file
Run Code Online (Sandbox Code Playgroud)
我想把它变成:
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
Run Code Online (Sandbox Code Playgroud)
目标是您可以组合文件夹并获取原始文件夹的结构。
使用 powershell 可以实现这样的功能吗?我已经看到了一些使用 bash 和 dirsplit 的解决方案,但我真的很想将其保留在 powershell 中,除非有一些现有软件的简单干净的解决方案。
我忘记补充一点,文件夹可能不仅包含文件,有时还包含文件夹。有没有一种解决方案可以在一定程度上递归地执行此操作?
考虑到我没有经常使用 powershell,感觉好像我错过了一些东西。
您描述的分区类型也称为装箱问题。
对此的一个相当快的解决方案被称为首次适应算法- 想象无限行有限大小的箱子,然后简单地将每个项目打包到下一个有空间的箱子中。这可以通过首先包装最大的物品(通过预先对物品进行排序)来进一步优化。
下面是一个有点冗长的实现:
# 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
}
}
Run Code Online (Sandbox Code Playgroud)
您可以轻松地跳过将每个项目分配给列表的中间步骤,并直接移动文件,但我觉得将示例分成两部分可以使我们想要做的事情更清晰/更易读。
| 归档时间: |
|
| 查看次数: |
2623 次 |
| 最近记录: |