2

我刚刚开始涉足 Powershell,在搜索了许多脚本之后,我还没有找到一个有效的脚本。(也许我运行不正确,但我启用了正确的管理权限等)

我的要求:
一个Powershell脚本
- 递归地遍历目录结构,到最后一级
- 将所有内容(具有任何扩展名的文件)从文件所在的位置向上移动一级 - 移动
后,删除文件所在的文件夹从

    ◘ 之前 ◘

    古典
    ├─莫扎特-5
    │ └─莫扎特-欧洲作曲家
    │ ├─01-交响乐.mp3
    │ └─03-symphony.mp3
    │
    ├─Bach-7
    │ └─巴赫
    │ ├─02-symphony.ogg
    │ └─04-音乐会.wav
    │
    │
    └─维瓦尔第2号
      └─Vivaldi-Not-The-Browser
        ├─01-track.m4a
        └─02-solo.mp4

    =================================================

    ◘ 之后 ◘

    古典
    ├─莫扎特-5
    │ ├─01-交响乐.mp3
    │ └─03-symphony.mp3
    │
    ├─Bach-7
    │ ├─02-symphony.ogg
    │ └─04-音乐会.wav
    │
    └─维瓦尔第2号
      ├─01-track.m4a
      └─02-solo.mp4



注意:
- 基本文件夹可以称为任何文件夹,例如 Classical、Rock 等
(因此,理想情况下,我会从所有子文件夹所在的基本文件夹内部运行 Powershell 脚本)
- 文件夹深度可以是1 级或多级深度
(99.9% 的情况下,深度为 2-3 级,即
Root - Music
1st - _Classical_
2nd - Mozart-5
3rd - Mozart-European-Composers

1st - _Indian Classical_
2nd - Ravi
3rd - Ravi Masterpieces
2nd - Zakir
3rd - Zakir-Solo-Piece


4

3 回答 3

1

好吧,这让我走了一段时间,但我终于想通了。它需要一个递归函数(一个调用自身的函数)。这种方法并不关心你的树有多深,所以它可以处理超过 3 层深度的 0.1% 的案例。

Clear-Host

Function Check-Dir {

  Param (
    [Parameter(Mandatory=$True)]
      [String] $Path
  )

  $GCIArgs = @{Path = "$Path"}

  $Files = Get-ChildItem @GCIArgs | 
             Where-Object {-not $_.PSIsContainer}

#--- If no Subs returns $Null! ---
  $Subs  = Get-childitem @GCIArgs | 
             Where-Object {$_.PSIsContainer}

  If ($Null -ne $Subs) {
    ForEach ($S in $Subs) {
      $Bottom = $False
      $DelDir = Check-Dir -Path "$($S.FullName)"
      If ($DelDir) { 
        $S | Remove-Item -Force 
      }
    }
  }

  Else {
   $MIArgs = @{Destination = "$("$Path" + "\..")"
               Force       = $True}
   $Files | Move-Item @MIArgs
   $Bottom = $True         
  }

  If ($Bottom) {$True}
  Else         {$False}

} #End Function Check-Dir

#-------------- Main Program -----------------

$BaseDir = "G:\Test\Music"

Check-dir -path "$BaseDir"

高温高压

于 2020-06-19T02:16:17.263 回答
0

这在我的测试中有效。

Clear-Host

$BaseDir = "G:\Test\America"

$GCIArgs = @{Path    = "$BaseDir"
             Exclude = "*.ini"
             Recurse = $True}
$Files = Get-childitem @GCIArgs
$Files | Where-Object {-not $_.PSIsContainer} |
         Move-Item     -Destination "$BaseDir" 

$Files | Where-Object {$_.PSIsContainer} |
         Remove-Item -Force -Recurse

注意:如果要保存 .ini 文件,可以去掉 Exclude 参数。

高温高压

于 2020-06-17T20:36:57.417 回答
0

我能够混合使用一个对我有用的解决方案,即。
两步过程:
1)将所有文件向上移动 1 级,到其父级
2)由于源文件夹现在是空的,因为文件被向上移动了 1 级,所以下一个任务是递归删除所有空的文件夹

考虑到这一点:

Get-ChildItem '*\*\*' | Move-Item -Destination { $_.Directory.Parent.FullName }
Get-ChildItem -recurse | Where {$_.PSIsContainer -and `
@(Get-ChildItem -Lit $_.Fullname -r | Where {!$_.PSIsContainer}).Length -eq 0} |
Remove-Item -recurse

注意:
○ 我还应该提到我的文件夹名称包含“[”和“]”,这对 Powershell 来说变得具有挑战性,因为Get-ChildItem它不起作用。
请参阅此处:Option -recurse 有时不适用于 PowerShell cmdlet get-childitem

○ 另外,由于我的文件夹名称中包含“[”和“]”,删除这些文件夹也需要一些“技巧”。
起初,我选择了这个解决方案
-如何递归删除 PowerShell 中的所有空文件夹?
但是,这是一个运行良好的方法:
如何使用 PowerShell 删除空子文件夹?
(灵感来自:递归删除空文件夹的 PowerShell 脚本

于 2020-06-18T16:25:50.370 回答