删除目录中不包含特定扩展名的所有子文件夹

删除目录中不包含特定扩展名的所有子文件夹

问题:是否可以删除某个目录中不包含特定文件类型(例如音乐文件(mp3/flac/wav/etc))的每个文件夹?

我使用 Mp3Tag 重新标记了一些文件,并将它们移动到了新的文件夹结构中:

\Artist\Album\Artist Name - Album - Track Number - Track.ext

示例文件结构

这会导致旧子文件夹中没有任何音乐文件(mp3/flac/wav/etc),但留下文件等cover.jpg的残余。log

例如,在上图中,我想删除“ \Adele - 25 Album”。最终,我想删除没有任何音乐文件(mp3/flac/wav/等)的子文件夹。

我对此做了一些努力,但我真的想不出任何有成效的东西,而且也遇到了困难。我想知道是否有人可以为我提供一些指导来完成这项任务。

答案1

  • 更新:

删除文件夹{和/或[以名义调用:

cmd.exe /s rm some_folder_with_{special}_character_they_[name]`:

cmd /v/s/c "del /q /f "%%~dpnxi*.*" && rmdir /q "%%~dpnxi" && echo\Deleted:"%%~dpnxi"

@echo off && setlocal enabledelayedexpansion

set "_mp3dir=F:\SUPER_USER\Q1507690\Organize"
set "_filter=%temp%\_filter_audio_!random!.log"

set "_audios=aa3,aac,aif,flac,m3u,m4a,mka,mp3,mpa,mpc,oga,ogg,pla,wav,wma"
type nul >"!_filter!" && for %%i in (!_audios!)do >>"!_filter!" echo=.%%~i

for /d /r "%_mp3dir%" %%i in (*)do tree /a /f "%%~fi"|find "\-" >nul || set "_rm_dir=yEp" && (for /f tokens^=* %%# in ('
     2^>nul %__APPDIR__%where.exe "%%~dpnxi:*"')do type "!_filter!" | find /i "%%~x#" >nul && set "_rm_dir=nOp"
     if "!_rm_dir!"=="yEp" cmd /v/s/c "echo\del /q /f "%%~dpnxi\*.*" && echo\rmdir /q "%%~dpnxi" && echo\Deleted:"%%~dpnxi"
     )

set "_filter="<nul & del /q /f "%temp%\_filter_audio_*.log" & endlocal & goto :EOF

测试一下,如果觉得没问题,就删除它echo以下命令:

if "!_rm_dir!"=="yEp" cmd /v/s/c "echo\del /q /f "%%~dpnxi*.*" && echo\rmdir /q "%%~dpnxi" && echo\Deleted:"%%~dpnxi"

@echo off && setlocal enabledelayedexpansion

set "_mp3dir=F:\Organize"
set "_filter=%temp%\_filter_audio_!random!.log"

set "_audios=aa3,aac,aif,flac,m3u,m4a,mka,mp3,mpa,mpc,oga,ogg,pla,wav,wma"
type nul >"!_filter!" && for %%i in (!_audios!)do >>"!_filter!" echo=.%%~i

for /d /r "%_mp3dir%" %%i in (*)do tree /a /f "%%~fi"|find "\-" >nul || set "_rm_dir=yEp" && (for /f tokens^=* %%# in ('
     2^>nul %__APPDIR__%where.exe "%%~dpni:*"')do type "!_filter!" | find /i "%%~x#" >nul && set "_rm_dir=nOp"
     if /i "!_rm_dir!" == "yEp" echo\rmdir /q "%%~dpni" ^&^& Folder: "%%~dpni" was deleted^!!
    )

set "_filter="<nul & del /q /f "%temp%\_filter_audio_*.log" & endlocal & goto :EOF
  1. 定义(set)所有必要的扩展名以将音频文件保存在文件夹树中:
set "_audios=aa3,aac,aif,flac,m3u,m4a,mka,mp3,mpa,mpc,oga,ogg,pla,wav,wma"
  1. findstr将所有扩展名保存在一个文件中,以便在检查每个文件夹(每个级别的最后一个)列表输出时使用,使用先前定义的变量for中的循环:_audios
type nul >"!_filter!" && for %%i in (!_audios!)do >>"!_filter!" echo=.%%~i
  1. 对文件夹使用特定的循环并同时递归(for /d /r)检查循环中的当前文件夹是否是当前级别的最后一个文件夹(tree ..|find "\-"),即下面没有子文件夹......
for /d /r "%_mp3dir%" %%i in (*)do tree /a /f "%%~fi"|find "\-" >nul

笔记:该方法在此进行了详细说明回答

  1. 使用for /f循环附加列出每个子文件夹最后一级的文件,并使用命令where将文件扩展名重定向到以find搜索日志文件以查找发生的情况。
(for /f tokens^=* %%# in ('
     2^>nul %__APPDIR__%where.exe "%%~dpni:*"')do type "!_filter!" | find /i "%%~x#" >nul
  1. find命令在循环输出处找到音频扩展名时,变量_rm_dir会将字符串从 更改yEpnOp,从而防止当前文件夹被删除/移除,而当发生相反情况时,即没有现有文件或没有具有音频扩展名的文件时,变量将保留 的_rm_diryEp
set "_rm_dir=yEp" && (for /f tokens^=* %%# in ('
     2^>nul %__APPDIR__%where.exe "%%~dpni:*"')do type "!_filter!" | find /i "%%~x#" >nul && set "_rm_dir=nOp"
  1. 在上一个循环完成后,当变量与字符串的if比较条件为真时,将采取行动(如有必要)删除/移除没有音频文件的文件夹:_rm_diryEp
if /i "!_rm_dir!" == "yEp" echo\rmdir /q "%%~dpni" ^&^& Folder: "%%~dpni" was deleted^!!
  1. 测试并检查输出,如果看起来正确,只需从中删除echo\和特定 :^^&^&
if /i "!_rm_dir!" == "yEp" echo\rmdir /q "%%~dpni" ^&^& Folder: "%%~dpni" was deleted^!!
  1. echo命令用于预览脚本执行的操作
if /i "!_rm_dir!" == "yEp" echo\rmdir /q "%%~dpni" ^&^& Folder: "%%~dpni" was deleted^!!
  1. [Refer to the Update]要使用命令删除名称中带有特殊字符的文件夹,只需cmd使用标志调用/s

cmd /v/s/c "del /q /f "%%~dpnxi*.*" && rmdir /q "%%~dpnxi" && echo\Deleted:"%%~dpnxi"

rmdir /q "F:\SUPER_USER\Q1553051\Organize\540x21" && Folder: "F:\SUPER_USER\Q1553051\Organize\540x21" was deleted
rmdir /q "F:\SUPER_USER\Q1553051\Organize\54x320" && Folder: "F:\SUPER_USER\Q1553051\Organize\54x320" was deleted
rmdir /q "F:\SUPER_USER\Q1553051\Organize\12x349" && Folder: "F:\SUPER_USER\Q1553051\Organize\12x349" was deleted
rmdir /q "F:\SUPER_USER\Q1553051\Organize\543x21" && Folder: "F:\SUPER_USER\Q1553051\Organize\543x21" was deleted
rmdir /q "F:\SUPER_USER\Q1553051\Organize\123x45" && Folder: "F:\SUPER_USER\Q1553051\Organize\123x45" was deleted
rmdir /q "F:\SUPER_USER\Q1553051\Organize\12x346" && Folder: "F:\SUPER_USER\Q1553051\Organize\12x346" was deleted
rmdir /q "F:\SUPER_USER\Q1553051\Organize\empty_" && Folder: "F:\SUPER_USER\Q1553051\Organize\empty_" was deleted

但是,请考虑关注评论@somebadhat:
重命名F:\!OrganizeF:\Organize

尝试通过删除来重命名您的文件夹!,即使只是为了运行此脚本。

答案2

电源外壳:

使用-LiteralPath带有Remove-Itemallallows 的参数可以处理名称中的特殊字符。

$Source = 'F:\Organize'
$KeepExts = '.mp3', '.flac', '.wav'

# Directories with files to keep
$Keep = gci $Source -file -recurse |
   Where Extension -in $KeepExts |
      Select -expand DirectoryName -unique

# Directories with no subfolders
$LeafDirs = gci $Source -dir -Recurse |
   Where { (!(gci $_.FullName -dir)) } |
      select -expand FullName

$ToDelete = $LeafDirs | Where { $_ -notIn $Keep }

Remove-Item -LiteralPath $ToDelete -recurse

答案3

  1. 正如之前的评论中提到的,为了简单起见,最好!从所有文件夹名称中删除感叹号,以便 PowerShell获取子项可以顺利开始工作。

    笔记:清理过程完全完成后,您可以根据需要轻松地将感叹号添加回任何文件夹名称。

  2. 然后,您可以使用我提供的下面的 PowerShell 脚本作为示例来执行您需要执行的操作,仅删除文件夹和所有不包含您需要保留的媒体文件扩展名的文件夹内容。

重要物品

  • 您将需要将特定的文件扩展名添加到$Filter = @("*.aac","*.mp3","*.wav","*.<ext>","*.<ext>","...","...","*.<ext>");脚本顶部的变量中,以便它知道从删除过程中排除这些目录,因为这些目录包含您希望保留的文件夹内容。

  • 此过程首先通过运行清除所有没有文件或文件夹的空目录Robocopy <dest> <dest> /S /MOVE,然后从不包含您要保留的文件扩展名的文件夹中删除文件后,它将在最后运行此操作以清除任何其他空目录。

电源外壳

$Src = "F:\Organize"
$Filter = @("*.aac","*.mp3","*.wav","*.flac");

Robocopy $Src $Src /S /MOVE 

$AllDirs = (Get-ChildItem $Src -Directory -Recurse).FullName;

$WipeDirs = @();
$AllDirs | % { Process {
    If(!(Get-ChildItem -LiteralPath "$_" -File -Include $Filter -Recurse).DirectoryName){ 
        [array]$WipeDirs += "$_" 
        }
    }};

$WipeDirs | % { Process {
    Get-ChildItem $_ | Remove-Item -Force;
    }};

$AllDirs+$Src | % {
    $nonFilterFiles = (Get-ChildItem -LiteralPath "$_" -File).FullName; 
    $FilterFiles    = (Get-ChildItem -Path "$_\*" -File -Include $Filter).FullName;

    If($FilterFiles.Count -ge 1){ Return; };
    If($FilterFiles.Count -eq $nonFilterFiles.Count){ Return; };
    If(!$FilterFiles){ $nonFilterFiles | % { Process { Remove-Item -LiteralPath $_ -Force; }}};
    If((!$FilterFiles) -and $nonFilterFiles -ge 1){ $nonFilterFiles | % { Process { Remove-Item -LiteralPath $_ -Force; }}};

    };

Robocopy $Src $Src /S /MOVE 

支持资源

相关内容